@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.
Files changed (419) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/Invect-CWpIwZ5F.js +92738 -0
  4. package/dist/Invect.d.ts +25 -0
  5. package/dist/InvectShell.d.ts +14 -0
  6. package/dist/api/agent-tools.api.d.ts +1 -0
  7. package/dist/api/client.d.ts +207 -0
  8. package/dist/api/credentials.api.d.ts +47 -0
  9. package/dist/api/executions.api.d.ts +43 -0
  10. package/dist/api/flows.api.d.ts +100 -0
  11. package/dist/api/index.d.ts +9 -0
  12. package/dist/api/node-data.api.d.ts +66 -0
  13. package/dist/api/query-keys.d.ts +22 -0
  14. package/dist/api/triggers.api.d.ts +44 -0
  15. package/dist/api/types.d.ts +147 -0
  16. package/dist/api/use-flow-run-stream.d.ts +12 -0
  17. package/dist/assets/invect-branding.d.ts +4 -0
  18. package/dist/assets/provider-icons/index.d.ts +8 -0
  19. package/dist/babel-C9OtljFZ.js +9721 -0
  20. package/dist/components/PageLayout.d.ts +17 -0
  21. package/dist/components/chat/ChatInput.d.ts +17 -0
  22. package/dist/components/chat/ChatMessageList.d.ts +14 -0
  23. package/dist/components/chat/ChatModelSelector.d.ts +11 -0
  24. package/dist/components/chat/ChatPanel.d.ts +19 -0
  25. package/dist/components/chat/ChatPromptOverlay.d.ts +13 -0
  26. package/dist/components/chat/ChatProviderSelector.d.ts +9 -0
  27. package/dist/components/chat/ChatSettingsPanel.d.ts +11 -0
  28. package/dist/components/chat/InlineCredentialSetup.d.ts +9 -0
  29. package/dist/components/chat/MarkdownRenderer.d.ts +7 -0
  30. package/dist/components/chat/chat-memory.d.ts +21 -0
  31. package/dist/components/chat/chat.store.d.ts +416 -0
  32. package/dist/components/chat/index.d.ts +5 -0
  33. package/dist/components/chat/use-chat.d.ts +28 -0
  34. package/dist/components/credentials/CreateCredentialModal.d.ts +13 -0
  35. package/dist/components/credentials/CredentialDetailDialog.d.ts +17 -0
  36. package/dist/components/credentials/EditCredentialModal.d.ts +11 -0
  37. package/dist/components/credentials/OAuth2ConnectButton.d.ts +38 -0
  38. package/dist/components/credentials/OAuth2ProviderSelector.d.ts +15 -0
  39. package/dist/components/credentials/credential-utils.d.ts +12 -0
  40. package/dist/components/credentials/index.d.ts +9 -0
  41. package/dist/components/dashboard/FailedRunsAlert.d.ts +3 -0
  42. package/dist/components/dashboard/FlowCard.d.ts +7 -0
  43. package/dist/components/dashboard/RecentActivityTable.d.ts +9 -0
  44. package/dist/components/dashboard/StatCard.d.ts +10 -0
  45. package/dist/components/dashboard/index.d.ts +5 -0
  46. package/dist/components/dashboard/status-helpers.d.ts +5 -0
  47. package/dist/components/flow-editor/ActionsSidebar.d.ts +2 -0
  48. package/dist/components/flow-editor/FlowEditor.d.ts +21 -0
  49. package/dist/components/flow-editor/FlowHeader.d.ts +9 -0
  50. package/dist/components/flow-editor/FlowLayout.d.ts +24 -0
  51. package/dist/components/flow-editor/ModeSwitcher.d.ts +7 -0
  52. package/dist/components/flow-editor/NodeSidebar.d.ts +24 -0
  53. package/dist/components/flow-editor/RunControls.d.ts +12 -0
  54. package/dist/components/flow-editor/ToolConfigPanel.d.ts +16 -0
  55. package/dist/components/flow-editor/ValidationPanel.d.ts +5 -0
  56. package/dist/components/flow-editor/flow-editor.store.d.ts +1 -0
  57. package/dist/components/flow-editor/index.d.ts +6 -0
  58. package/dist/components/flow-editor/inline-edit.d.ts +10 -0
  59. package/dist/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.d.ts +26 -0
  60. package/dist/components/flow-editor/node-config-panel/CredentialCombobox.d.ts +21 -0
  61. package/dist/components/flow-editor/node-config-panel/CredentialsSection.d.ts +19 -0
  62. package/dist/components/flow-editor/node-config-panel/DroppableInput.d.ts +20 -0
  63. package/dist/components/flow-editor/node-config-panel/DynamicSelectField.d.ts +22 -0
  64. package/dist/components/flow-editor/node-config-panel/JsonPreviewPanel.d.ts +25 -0
  65. package/dist/components/flow-editor/node-config-panel/NodeConfigPanel.d.ts +14 -0
  66. package/dist/components/flow-editor/node-config-panel/NodeConfigPanelHeader.d.ts +15 -0
  67. package/dist/components/flow-editor/node-config-panel/ParametersSection.d.ts +16 -0
  68. package/dist/components/flow-editor/node-config-panel/SearchableSelectField.d.ts +17 -0
  69. package/dist/components/flow-editor/node-config-panel/SwitchCasesField.d.ts +18 -0
  70. package/dist/components/flow-editor/node-config-panel/hooks/index.d.ts +2 -0
  71. package/dist/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.d.ts +24 -0
  72. package/dist/components/flow-editor/node-config-panel/hooks/use-node-execution.d.ts +46 -0
  73. package/dist/components/flow-editor/node-config-panel/hooks/use-upstream-slots.d.ts +16 -0
  74. package/dist/components/flow-editor/node-config-panel/panels/AgentToolsPanel.d.ts +18 -0
  75. package/dist/components/flow-editor/node-config-panel/panels/ConfigurationPanel.d.ts +49 -0
  76. package/dist/components/flow-editor/node-config-panel/panels/DataMapperPane.d.ts +40 -0
  77. package/dist/components/flow-editor/node-config-panel/panels/InputPanel.d.ts +49 -0
  78. package/dist/components/flow-editor/node-config-panel/panels/OutputPanel.d.ts +7 -0
  79. package/dist/components/flow-editor/node-config-panel/panels/index.d.ts +4 -0
  80. package/dist/components/flow-editor/node-config-panel/types.d.ts +19 -0
  81. package/dist/components/flow-editor/node-config-panel/use-node-config-panel-store.d.ts +49 -0
  82. package/dist/components/flow-editor/node-config-panel/use-node-config-state.d.ts +26 -0
  83. package/dist/components/flow-editor/node-config-panel/use-run-node.d.ts +16 -0
  84. package/dist/components/flow-editor/node-config-panel/utils.d.ts +9 -0
  85. package/dist/components/flow-editor/serialize-to-sdk.d.ts +20 -0
  86. package/dist/components/flow-editor/toolbar-context.d.ts +2 -0
  87. package/dist/components/flow-editor/use-copy-paste.d.ts +7 -0
  88. package/dist/components/flow-editor/use-copy-paste.types.d.ts +38 -0
  89. package/dist/components/flow-editor/use-flow-editor.d.ts +44 -0
  90. package/dist/components/flow-runs-table/FlowRunsTable.d.ts +6 -0
  91. package/dist/components/flow-runs-table/index.d.ts +1 -0
  92. package/dist/components/flow-viewer/FlowRunsView.d.ts +7 -0
  93. package/dist/components/flow-viewer/FlowStatusView.d.ts +21 -0
  94. package/dist/components/flow-viewer/RunSelector.d.ts +13 -0
  95. package/dist/components/flow-viewer/RunsSidebar.d.ts +14 -0
  96. package/dist/components/flow-viewer/agent-tool-executions-list.d.ts +7 -0
  97. package/dist/components/flow-viewer/index.d.ts +1 -0
  98. package/dist/components/flow-viewer/logs-panel.d.ts +18 -0
  99. package/dist/components/flow-viewer/use-execution-log-data.d.ts +113 -0
  100. package/dist/components/graph/BatchFlowEdge.d.ts +33 -0
  101. package/dist/components/graph/LayoutSelector.d.ts +9 -0
  102. package/dist/components/graph/index.d.ts +47 -0
  103. package/dist/components/graph/styleUtils.d.ts +124 -0
  104. package/dist/components/nodes/AgentConfigPanel.d.ts +24 -0
  105. package/dist/components/nodes/AgentNode.d.ts +8 -0
  106. package/dist/components/nodes/AgentToolsBox.d.ts +41 -0
  107. package/dist/components/nodes/NodeAppendix.d.ts +19 -0
  108. package/dist/components/nodes/NodeStatusIndicator.d.ts +30 -0
  109. package/dist/components/nodes/NodeViewContext.d.ts +18 -0
  110. package/dist/components/nodes/ToolParamField.d.ts +28 -0
  111. package/dist/components/nodes/ToolSelectorModal.d.ts +80 -0
  112. package/dist/components/nodes/ToolSelectorParts.d.ts +30 -0
  113. package/dist/components/nodes/UniversalNode.d.ts +2 -0
  114. package/dist/components/nodes/createContextAwareNodes.d.ts +6 -0
  115. package/dist/components/nodes/index.d.ts +22 -0
  116. package/dist/components/nodes/nodeRegistry.d.ts +13 -0
  117. package/dist/components/nodes/withNodeContext.d.ts +7 -0
  118. package/dist/components/shared/InvectLoader.d.ts +8 -0
  119. package/dist/components/shared/InvectLogo.d.ts +9 -0
  120. package/dist/components/shared/ProviderIcon.d.ts +23 -0
  121. package/dist/components/side-menu/side-menu.d.ts +4 -0
  122. package/dist/components/sidebar/BaseSidebar.d.ts +17 -0
  123. package/dist/components/sidebar/index.d.ts +1 -0
  124. package/dist/components/triggers/CronPreview.d.ts +12 -0
  125. package/dist/components/triggers/index.d.ts +1 -0
  126. package/dist/components/ui/alert-dialog.d.ts +18 -0
  127. package/dist/components/ui/badge.d.ts +9 -0
  128. package/dist/components/ui/button.d.ts +13 -0
  129. package/dist/components/ui/card.d.ts +9 -0
  130. package/dist/components/ui/codemirror-js-editor.d.ts +25 -0
  131. package/dist/components/ui/codemirror-json-editor.d.ts +18 -0
  132. package/dist/components/ui/codemirror-nunjucks-editor.d.ts +13 -0
  133. package/dist/components/ui/codemirror-vscode-theme.d.ts +24 -0
  134. package/dist/components/ui/collapsible.d.ts +6 -0
  135. package/dist/components/ui/command.d.ts +18 -0
  136. package/dist/components/ui/dialog.d.ts +18 -0
  137. package/dist/components/ui/dropdown-menu.d.ts +25 -0
  138. package/dist/components/ui/empty-state.d.ts +21 -0
  139. package/dist/components/ui/input.d.ts +3 -0
  140. package/dist/components/ui/label.d.ts +4 -0
  141. package/dist/components/ui/popover.d.ts +10 -0
  142. package/dist/components/ui/resizable.d.ts +8 -0
  143. package/dist/components/ui/scroll-area.d.ts +5 -0
  144. package/dist/components/ui/select.d.ts +18 -0
  145. package/dist/components/ui/separator.d.ts +4 -0
  146. package/dist/components/ui/slider.d.ts +4 -0
  147. package/dist/components/ui/switch.d.ts +3 -0
  148. package/dist/components/ui/table.d.ts +10 -0
  149. package/dist/components/ui/textarea.d.ts +3 -0
  150. package/dist/components/ui/tooltip.d.ts +7 -0
  151. package/dist/components/ui/tree-view.d.ts +107 -0
  152. package/dist/contexts/AgentToolCallbacksContext.d.ts +23 -0
  153. package/dist/contexts/ApiContext.d.ts +11 -0
  154. package/dist/contexts/FlowDataContext.d.ts +9 -0
  155. package/dist/contexts/NodeRegistryContext.d.ts +14 -0
  156. package/dist/contexts/PluginRegistryContext.d.ts +39 -0
  157. package/dist/contexts/ThemeProvider.d.ts +18 -0
  158. package/dist/contexts/ValidationContext.d.ts +22 -0
  159. package/dist/demo/DemoInvect.d.ts +11 -0
  160. package/dist/demo/FlowViewer.d.ts +31 -0
  161. package/dist/demo/demo-api-client.d.ts +33 -0
  162. package/dist/demo/index.d.ts +6 -0
  163. package/dist/demo/sample-data.d.ts +1538 -0
  164. package/dist/demo.d.ts +2 -0
  165. package/dist/demo.js +2774 -0
  166. package/dist/estree-ClbRfS-1.js +7076 -0
  167. package/dist/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
  168. package/dist/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
  169. package/dist/fonts/geist-latin-wght-normal.woff2 +0 -0
  170. package/dist/fonts/iosevka-latin-400-normal.woff2 +0 -0
  171. package/dist/hooks/index.d.ts +1 -0
  172. package/dist/hooks/use-document-title.d.ts +1 -0
  173. package/dist/hooks/use-flow-data.d.ts +22 -0
  174. package/dist/hooks/use-invect-portal-class.d.ts +21 -0
  175. package/dist/hooks/useFlowEditorStore.d.ts +1 -0
  176. package/dist/index.css +3 -0
  177. package/dist/index.d.ts +22 -0
  178. package/dist/index.js +717 -0
  179. package/dist/lib/utils.d.ts +2 -0
  180. package/dist/prettier.d.ts +13 -0
  181. package/dist/routes/all-flow-runs.d.ts +5 -0
  182. package/dist/routes/credentials.d.ts +5 -0
  183. package/dist/routes/flow-route-layout.d.ts +19 -0
  184. package/dist/routes/flow-runs.d.ts +5 -0
  185. package/dist/routes/flow.d.ts +5 -0
  186. package/dist/routes/home.d.ts +5 -0
  187. package/dist/services/index.d.ts +1 -0
  188. package/dist/standalone-C3Df7W52.js +3463 -0
  189. package/dist/stores/executionViewStore.d.ts +64 -0
  190. package/dist/stores/flow-editor.store.d.ts +137 -0
  191. package/dist/stores/flowEditorStore.d.ts +1 -0
  192. package/dist/stores/index.d.ts +2 -0
  193. package/dist/stores/uiStore.d.ts +45 -0
  194. package/dist/types/agent-tools.types.d.ts +53 -0
  195. package/dist/types/index.d.ts +2 -0
  196. package/dist/types/node-definition.types.d.ts +85 -0
  197. package/dist/types/plugin.types.d.ts +100 -0
  198. package/dist/utils/credentialBranding.d.ts +8 -0
  199. package/dist/utils/credentialFiltering.d.ts +20 -0
  200. package/dist/utils/flowTransformations.d.ts +16 -0
  201. package/dist/utils/layoutUtils.d.ts +23 -0
  202. package/dist/utils/nodeReferenceUtils.d.ts +37 -0
  203. package/dist/vendor.d.ts +5 -0
  204. package/package.json +130 -0
  205. package/src/.DS_Store +0 -0
  206. package/src/Invect.tsx +229 -0
  207. package/src/InvectShell.tsx +55 -0
  208. package/src/api/agent-tools.api.ts +23 -0
  209. package/src/api/client.ts +899 -0
  210. package/src/api/credentials.api.ts +197 -0
  211. package/src/api/executions.api.ts +228 -0
  212. package/src/api/flows.api.ts +195 -0
  213. package/src/api/index.ts +17 -0
  214. package/src/api/node-data.api.ts +167 -0
  215. package/src/api/query-keys.ts +44 -0
  216. package/src/api/triggers.api.ts +120 -0
  217. package/src/api/types.ts +212 -0
  218. package/src/api/use-flow-run-stream.ts +206 -0
  219. package/src/app.css +560 -0
  220. package/src/assets/.DS_Store +0 -0
  221. package/src/assets/favicon.ico +0 -0
  222. package/src/assets/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
  223. package/src/assets/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
  224. package/src/assets/fonts/geist-latin-wght-normal.woff2 +0 -0
  225. package/src/assets/fonts/iosevka-latin-400-normal.woff2 +0 -0
  226. package/src/assets/invect-branding.ts +51 -0
  227. package/src/assets/provider-icons/anthropic.svg +1 -0
  228. package/src/assets/provider-icons/anthropic_light.svg +1 -0
  229. package/src/assets/provider-icons/github.svg +1 -0
  230. package/src/assets/provider-icons/github_light.svg +1 -0
  231. package/src/assets/provider-icons/gmail.svg +1 -0
  232. package/src/assets/provider-icons/google_calendar.svg +1 -0
  233. package/src/assets/provider-icons/google_docs.svg +1 -0
  234. package/src/assets/provider-icons/google_drive.svg +1 -0
  235. package/src/assets/provider-icons/google_sheets.svg +1 -0
  236. package/src/assets/provider-icons/index.ts +55 -0
  237. package/src/assets/provider-icons/linear.svg +1 -0
  238. package/src/assets/provider-icons/openai.svg +1 -0
  239. package/src/assets/provider-icons/postgres.svg +1 -0
  240. package/src/assets/provider-icons/slack.svg +1 -0
  241. package/src/assets/small-loader-dark.svg +22 -0
  242. package/src/assets/small-loader-light.svg +22 -0
  243. package/src/assets/small.svg +7 -0
  244. package/src/components/.DS_Store +0 -0
  245. package/src/components/PageLayout.tsx +55 -0
  246. package/src/components/chat/ChatInput.tsx +115 -0
  247. package/src/components/chat/ChatMessageList.tsx +788 -0
  248. package/src/components/chat/ChatModelSelector.tsx +208 -0
  249. package/src/components/chat/ChatPanel.tsx +243 -0
  250. package/src/components/chat/ChatPromptOverlay.tsx +150 -0
  251. package/src/components/chat/ChatProviderSelector.tsx +135 -0
  252. package/src/components/chat/ChatSettingsPanel.tsx +277 -0
  253. package/src/components/chat/InlineCredentialSetup.tsx +343 -0
  254. package/src/components/chat/MarkdownRenderer.tsx +140 -0
  255. package/src/components/chat/chat-memory.ts +88 -0
  256. package/src/components/chat/chat.store.ts +479 -0
  257. package/src/components/chat/index.ts +5 -0
  258. package/src/components/chat/use-chat.ts +473 -0
  259. package/src/components/credentials/CreateCredentialModal.tsx +609 -0
  260. package/src/components/credentials/CredentialDetailDialog.tsx +882 -0
  261. package/src/components/credentials/EditCredentialModal.tsx +399 -0
  262. package/src/components/credentials/OAuth2ConnectButton.tsx +288 -0
  263. package/src/components/credentials/OAuth2ProviderSelector.tsx +360 -0
  264. package/src/components/credentials/credential-utils.ts +99 -0
  265. package/src/components/credentials/index.ts +10 -0
  266. package/src/components/dashboard/FailedRunsAlert.tsx +67 -0
  267. package/src/components/dashboard/FlowCard.tsx +64 -0
  268. package/src/components/dashboard/RecentActivityTable.tsx +92 -0
  269. package/src/components/dashboard/StatCard.tsx +32 -0
  270. package/src/components/dashboard/index.ts +5 -0
  271. package/src/components/dashboard/status-helpers.tsx +102 -0
  272. package/src/components/flow-editor/ActionsSidebar.tsx +503 -0
  273. package/src/components/flow-editor/FlowEditor.tsx +1002 -0
  274. package/src/components/flow-editor/FlowHeader.tsx +87 -0
  275. package/src/components/flow-editor/FlowLayout.tsx +117 -0
  276. package/src/components/flow-editor/ModeSwitcher.tsx +49 -0
  277. package/src/components/flow-editor/NodeSidebar.tsx +343 -0
  278. package/src/components/flow-editor/RunControls.tsx +109 -0
  279. package/src/components/flow-editor/ToolConfigPanel.tsx +434 -0
  280. package/src/components/flow-editor/ValidationPanel.tsx +167 -0
  281. package/src/components/flow-editor/flow-editor.store.ts +2 -0
  282. package/src/components/flow-editor/index.ts +6 -0
  283. package/src/components/flow-editor/inline-edit.tsx +111 -0
  284. package/src/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.tsx +334 -0
  285. package/src/components/flow-editor/node-config-panel/CredentialCombobox.tsx +217 -0
  286. package/src/components/flow-editor/node-config-panel/CredentialsSection.tsx +154 -0
  287. package/src/components/flow-editor/node-config-panel/DroppableInput.tsx +45 -0
  288. package/src/components/flow-editor/node-config-panel/DynamicSelectField.tsx +223 -0
  289. package/src/components/flow-editor/node-config-panel/JsonPreviewPanel.tsx +134 -0
  290. package/src/components/flow-editor/node-config-panel/NodeConfigPanel.tsx +650 -0
  291. package/src/components/flow-editor/node-config-panel/NodeConfigPanelHeader.tsx +91 -0
  292. package/src/components/flow-editor/node-config-panel/ParametersSection.tsx +144 -0
  293. package/src/components/flow-editor/node-config-panel/SearchableSelectField.tsx +126 -0
  294. package/src/components/flow-editor/node-config-panel/SwitchCasesField.tsx +212 -0
  295. package/src/components/flow-editor/node-config-panel/hooks/index.ts +2 -0
  296. package/src/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.ts +284 -0
  297. package/src/components/flow-editor/node-config-panel/hooks/use-node-execution.ts +287 -0
  298. package/src/components/flow-editor/node-config-panel/hooks/use-upstream-slots.ts +310 -0
  299. package/src/components/flow-editor/node-config-panel/panels/AgentToolsPanel.tsx +837 -0
  300. package/src/components/flow-editor/node-config-panel/panels/ConfigurationPanel.tsx +383 -0
  301. package/src/components/flow-editor/node-config-panel/panels/DataMapperPane.tsx +456 -0
  302. package/src/components/flow-editor/node-config-panel/panels/InputPanel.tsx +338 -0
  303. package/src/components/flow-editor/node-config-panel/panels/OutputPanel.tsx +109 -0
  304. package/src/components/flow-editor/node-config-panel/panels/index.ts +4 -0
  305. package/src/components/flow-editor/node-config-panel/types.ts +20 -0
  306. package/src/components/flow-editor/node-config-panel/use-node-config-panel-store.ts +283 -0
  307. package/src/components/flow-editor/node-config-panel/use-node-config-state.ts +172 -0
  308. package/src/components/flow-editor/node-config-panel/use-run-node.ts +147 -0
  309. package/src/components/flow-editor/node-config-panel/utils.ts +73 -0
  310. package/src/components/flow-editor/serialize-to-sdk.ts +204 -0
  311. package/src/components/flow-editor/toolbar-context.ts +9 -0
  312. package/src/components/flow-editor/use-copy-paste.ts +575 -0
  313. package/src/components/flow-editor/use-copy-paste.types.ts +35 -0
  314. package/src/components/flow-editor/use-flow-editor.ts +241 -0
  315. package/src/components/flow-runs-table/FlowRunsTable.tsx +631 -0
  316. package/src/components/flow-runs-table/index.ts +1 -0
  317. package/src/components/flow-viewer/FlowRunsView.tsx +268 -0
  318. package/src/components/flow-viewer/FlowStatusView.tsx +351 -0
  319. package/src/components/flow-viewer/RunSelector.tsx +422 -0
  320. package/src/components/flow-viewer/RunsSidebar.tsx +125 -0
  321. package/src/components/flow-viewer/agent-tool-executions-list.tsx +298 -0
  322. package/src/components/flow-viewer/index.ts +1 -0
  323. package/src/components/flow-viewer/logs-panel.tsx +567 -0
  324. package/src/components/flow-viewer/use-execution-log-data.ts +374 -0
  325. package/src/components/graph/BatchFlowEdge.tsx +229 -0
  326. package/src/components/graph/LayoutSelector.tsx +42 -0
  327. package/src/components/graph/index.ts +61 -0
  328. package/src/components/graph/styleUtils.ts +375 -0
  329. package/src/components/nodes/.DS_Store +0 -0
  330. package/src/components/nodes/AgentConfigPanel.tsx +1033 -0
  331. package/src/components/nodes/AgentNode.tsx +298 -0
  332. package/src/components/nodes/AgentToolsBox.tsx +193 -0
  333. package/src/components/nodes/NodeAppendix.tsx +98 -0
  334. package/src/components/nodes/NodeStatusIndicator.tsx +74 -0
  335. package/src/components/nodes/NodeViewContext.tsx +45 -0
  336. package/src/components/nodes/ToolParamField.tsx +282 -0
  337. package/src/components/nodes/ToolSelectorModal.tsx +648 -0
  338. package/src/components/nodes/ToolSelectorParts.tsx +505 -0
  339. package/src/components/nodes/UniversalNode.tsx +356 -0
  340. package/src/components/nodes/createContextAwareNodes.ts +19 -0
  341. package/src/components/nodes/index.ts +45 -0
  342. package/src/components/nodes/nodeRegistry.ts +50 -0
  343. package/src/components/nodes/withNodeContext.tsx +55 -0
  344. package/src/components/shared/InvectLoader.tsx +59 -0
  345. package/src/components/shared/InvectLogo.tsx +59 -0
  346. package/src/components/shared/ProviderIcon.tsx +115 -0
  347. package/src/components/side-menu/side-menu.tsx +267 -0
  348. package/src/components/sidebar/BaseSidebar.tsx +148 -0
  349. package/src/components/sidebar/index.ts +1 -0
  350. package/src/components/triggers/CronPreview.tsx +243 -0
  351. package/src/components/triggers/index.ts +1 -0
  352. package/src/components/ui/alert-dialog.tsx +152 -0
  353. package/src/components/ui/badge.tsx +39 -0
  354. package/src/components/ui/button.tsx +58 -0
  355. package/src/components/ui/card.tsx +75 -0
  356. package/src/components/ui/codemirror-js-editor.tsx +432 -0
  357. package/src/components/ui/codemirror-json-editor.tsx +816 -0
  358. package/src/components/ui/codemirror-nunjucks-editor.tsx +451 -0
  359. package/src/components/ui/codemirror-vscode-theme.ts +243 -0
  360. package/src/components/ui/collapsible.tsx +12 -0
  361. package/src/components/ui/command.tsx +162 -0
  362. package/src/components/ui/dialog.tsx +140 -0
  363. package/src/components/ui/dropdown-menu.tsx +232 -0
  364. package/src/components/ui/empty-state.tsx +93 -0
  365. package/src/components/ui/input.tsx +26 -0
  366. package/src/components/ui/label.tsx +19 -0
  367. package/src/components/ui/popover.tsx +53 -0
  368. package/src/components/ui/resizable.tsx +61 -0
  369. package/src/components/ui/scroll-area.tsx +56 -0
  370. package/src/components/ui/select.tsx +179 -0
  371. package/src/components/ui/separator.tsx +26 -0
  372. package/src/components/ui/slider.tsx +58 -0
  373. package/src/components/ui/switch.tsx +22 -0
  374. package/src/components/ui/table.tsx +90 -0
  375. package/src/components/ui/textarea.tsx +23 -0
  376. package/src/components/ui/tooltip.tsx +54 -0
  377. package/src/components/ui/tree-view.tsx +574 -0
  378. package/src/contexts/AgentToolCallbacksContext.tsx +31 -0
  379. package/src/contexts/ApiContext.tsx +51 -0
  380. package/src/contexts/FlowDataContext.tsx +21 -0
  381. package/src/contexts/NodeRegistryContext.tsx +54 -0
  382. package/src/contexts/PluginRegistryContext.tsx +182 -0
  383. package/src/contexts/ThemeProvider.tsx +106 -0
  384. package/src/contexts/ValidationContext.tsx +122 -0
  385. package/src/demo/DemoInvect.tsx +42 -0
  386. package/src/demo/FlowViewer.tsx +294 -0
  387. package/src/demo/demo-api-client.ts +246 -0
  388. package/src/demo/index.ts +28 -0
  389. package/src/demo/sample-data.ts +1980 -0
  390. package/src/hooks/index.ts +1 -0
  391. package/src/hooks/use-document-title.ts +8 -0
  392. package/src/hooks/use-flow-data.ts +144 -0
  393. package/src/hooks/use-invect-portal-class.ts +27 -0
  394. package/src/hooks/useFlowEditorStore.ts +2 -0
  395. package/src/index.ts +70 -0
  396. package/src/lib/utils.ts +6 -0
  397. package/src/prettier.d.ts +13 -0
  398. package/src/routes/all-flow-runs.tsx +27 -0
  399. package/src/routes/credentials.tsx +362 -0
  400. package/src/routes/flow-route-layout.tsx +113 -0
  401. package/src/routes/flow-runs.tsx +22 -0
  402. package/src/routes/flow.tsx +22 -0
  403. package/src/routes/home.tsx +282 -0
  404. package/src/services/index.ts +6 -0
  405. package/src/stores/executionViewStore.ts +211 -0
  406. package/src/stores/flow-editor.store.ts +738 -0
  407. package/src/stores/flowEditorStore.ts +2 -0
  408. package/src/stores/index.ts +10 -0
  409. package/src/stores/uiStore.ts +189 -0
  410. package/src/types/agent-tools.types.ts +64 -0
  411. package/src/types/index.ts +5 -0
  412. package/src/types/node-definition.types.ts +104 -0
  413. package/src/types/plugin.types.ts +123 -0
  414. package/src/utils/credentialBranding.ts +116 -0
  415. package/src/utils/credentialFiltering.ts +68 -0
  416. package/src/utils/flowTransformations.ts +137 -0
  417. package/src/utils/layoutUtils.ts +127 -0
  418. package/src/utils/nodeReferenceUtils.ts +135 -0
  419. package/src/vendor.d.ts +7 -0
@@ -0,0 +1,167 @@
1
+ import React from 'react';
2
+ import { useValidation } from '../../contexts/ValidationContext';
3
+ import {
4
+ FlowValidationError,
5
+ FlowValidationWarning,
6
+ FLOW_VALIDATION_ERROR_TYPES,
7
+ } from '@invect/core/types';
8
+
9
+ // Helper function to format node ID to a short display name
10
+ const formatNodeId = (nodeId: string): string => {
11
+ // Trim long UUIDs to something readable
12
+ if (nodeId.length > 20) {
13
+ return nodeId.slice(0, 8) + '…';
14
+ }
15
+ return nodeId;
16
+ };
17
+
18
+ interface ValidationPanelProps {
19
+ className?: string;
20
+ }
21
+
22
+ export function ValidationPanel({ className = '' }: ValidationPanelProps) {
23
+ const { validationResult, hasErrors, hasWarnings } = useValidation();
24
+
25
+ if (!validationResult || (!hasErrors && !hasWarnings)) {
26
+ return null;
27
+ }
28
+
29
+ const getErrorIcon = (error: FlowValidationError | FlowValidationWarning) => {
30
+ if (error.severity === 'error') {
31
+ return <span className="font-bold text-red-500">⚠️</span>;
32
+ }
33
+ return <span className="font-bold text-yellow-500">⚠</span>;
34
+ };
35
+
36
+ const getErrorTypeLabel = (type: string) => {
37
+ switch (type) {
38
+ // Errors (will cause execution failure)
39
+ case FLOW_VALIDATION_ERROR_TYPES.ERROR.INVALID_EDGE_REFERENCE:
40
+ return 'Invalid Edge Reference';
41
+ case FLOW_VALIDATION_ERROR_TYPES.ERROR.SELF_REFERENCING_EDGE:
42
+ return 'Self-Referencing Edge';
43
+ case FLOW_VALIDATION_ERROR_TYPES.ERROR.CIRCULAR_DEPENDENCY:
44
+ return 'Circular Dependency';
45
+ case FLOW_VALIDATION_ERROR_TYPES.ERROR.VALIDATION_SYSTEM_ERROR:
46
+ return 'Validation System Error';
47
+
48
+ // Warnings (flow will run but something looks off)
49
+ case FLOW_VALIDATION_ERROR_TYPES.WARNING.EMPTY_FLOW:
50
+ return 'Empty Flow';
51
+ case FLOW_VALIDATION_ERROR_TYPES.WARNING.ENTRY_NODE_HAS_INCOMING_EDGES:
52
+ return 'Entry Node Has Incoming Edges';
53
+ case FLOW_VALIDATION_ERROR_TYPES.WARNING.DISCONNECTED_NODE:
54
+ return 'Disconnected Node';
55
+ case FLOW_VALIDATION_ERROR_TYPES.WARNING.DUPLICATE_EDGE:
56
+ return 'Duplicate Edge';
57
+
58
+ // Generic fallback
59
+ default:
60
+ return 'Validation Issue';
61
+ }
62
+ };
63
+
64
+ return (
65
+ <div className={`bg-background border-l border-b h-full border-border p-4 ${className}`}>
66
+ <div className="mb-4">
67
+ <h3 className="text-lg font-semibold text-foreground">Flow Validation</h3>
68
+ <div className="text-sm text-muted-foreground">
69
+ {hasErrors && (
70
+ <span className="font-medium text-red-600">
71
+ {validationResult.isValid ? 0 : validationResult.errors.length} error
72
+ {validationResult.isValid ? 's' : validationResult.errors.length !== 1 ? 's' : ''}
73
+ </span>
74
+ )}
75
+ {hasErrors && hasWarnings && <span className="mx-2">•</span>}
76
+ {hasWarnings && (
77
+ <span className="font-medium text-yellow-600">
78
+ {validationResult.warnings?.length || 0} warning
79
+ {(validationResult.warnings?.length || 0) !== 1 ? 's' : ''}
80
+ </span>
81
+ )}
82
+ </div>
83
+ </div>
84
+
85
+ <div className="space-y-3">
86
+ {/* Errors */}
87
+ {!validationResult.isValid &&
88
+ validationResult.errors.map((error, index) => (
89
+ <ValidationItem
90
+ key={`error-${index}`}
91
+ error={error}
92
+ icon={getErrorIcon(error)}
93
+ typeLabel={getErrorTypeLabel(error.type)}
94
+ />
95
+ ))}
96
+
97
+ {/* Warnings */}
98
+ {validationResult.warnings?.map((warning, index) => (
99
+ <ValidationItem
100
+ key={`warning-${index}`}
101
+ error={warning}
102
+ icon={getErrorIcon(warning)}
103
+ typeLabel={getErrorTypeLabel(warning.type)}
104
+ />
105
+ ))}
106
+ </div>
107
+ </div>
108
+ );
109
+ }
110
+
111
+ interface ValidationItemProps {
112
+ error: FlowValidationError | FlowValidationWarning;
113
+ icon: React.ReactNode;
114
+ typeLabel: string;
115
+ }
116
+
117
+ function ValidationItem({ error, icon, typeLabel }: ValidationItemProps) {
118
+ const severityClass =
119
+ error.severity === 'error'
120
+ ? 'border-destructive/20 bg-destructive/5'
121
+ : 'border-border bg-muted/50';
122
+
123
+ return (
124
+ <div className={`border rounded-lg p-3 ${severityClass}`}>
125
+ <div className="flex items-start space-x-2">
126
+ <div className="flex-shrink-0 mt-0.5">{icon}</div>
127
+ <div className="flex-1 min-w-0">
128
+ <div className="text-sm font-medium text-foreground">{typeLabel}</div>
129
+ <div className="mt-1 text-sm text-muted-foreground">{error.message}</div>
130
+
131
+ {/* Additional context information */}
132
+ {'nodeId' in error && error.nodeId && (
133
+ <div className="mt-2 text-xs text-muted-foreground">
134
+ Node: {formatNodeId(error.nodeId)}
135
+ </div>
136
+ )}
137
+ {'sourceNodeId' in error &&
138
+ 'targetNodeId' in error &&
139
+ error.sourceNodeId &&
140
+ error.targetNodeId ? (
141
+ <div className="mt-1 text-xs text-muted-foreground">
142
+ Connection: {formatNodeId(error.sourceNodeId)} → {formatNodeId(error.targetNodeId)}
143
+ </div>
144
+ ) : null}
145
+
146
+ {/* Show additional edges for multiple inputs */}
147
+ {error.additionalContext &&
148
+ 'additionalEdgeIds' in error.additionalContext &&
149
+ error.additionalContext.additionalEdgeIds ? (
150
+ <div className="mt-1 text-xs text-muted-foreground">
151
+ Additional edges: {(error.additionalContext.additionalEdgeIds as string[]).join(', ')}
152
+ </div>
153
+ ) : null}
154
+
155
+ {/* Show cycle path for circular dependencies */}
156
+ {error.additionalContext &&
157
+ 'cyclePath' in error.additionalContext &&
158
+ error.additionalContext.cyclePath ? (
159
+ <div className="mt-1 text-xs text-muted-foreground">
160
+ Cycle: {(error.additionalContext.cyclePath as string[]).join(' → ')}
161
+ </div>
162
+ ) : null}
163
+ </div>
164
+ </div>
165
+ </div>
166
+ );
167
+ }
@@ -0,0 +1,2 @@
1
+ // Re-export from shared stores location — see stores/flow-editor.store.ts
2
+ export * from '~/stores/flow-editor.store';
@@ -0,0 +1,6 @@
1
+ export { FlowEditor } from './FlowEditor';
2
+ export type { FlowEditorProps } from './FlowEditor';
3
+ export { FlowWorkbenchView } from './FlowEditor';
4
+ export { NodeSidebar, type SidebarMode, type NodeSidebarProps } from './NodeSidebar';
5
+ export { ActionsSidebar } from './ActionsSidebar';
6
+ export { useFlowEditorStore, useIsLoading } from './flow-editor.store';
@@ -0,0 +1,111 @@
1
+ import { useState, useRef, useEffect } from 'react';
2
+ import { Input } from '../ui/input';
3
+ import { Button } from '../ui/button';
4
+ import { Pencil, Check, X } from 'lucide-react';
5
+ import { cn } from '../../lib/utils';
6
+
7
+ interface InlineEditProps {
8
+ value: string;
9
+ onChange: (value: string) => void;
10
+ placeholder?: string;
11
+ className?: string;
12
+ displayClassName?: string;
13
+ inputClassName?: string;
14
+ }
15
+
16
+ export function InlineEdit({
17
+ value,
18
+ onChange,
19
+ placeholder = 'Enter text',
20
+ className,
21
+ displayClassName,
22
+ inputClassName,
23
+ }: InlineEditProps) {
24
+ const [isEditing, setIsEditing] = useState(false);
25
+ const [editValue, setEditValue] = useState(value);
26
+ const inputRef = useRef<HTMLInputElement>(null);
27
+ const containerRef = useRef<HTMLDivElement>(null);
28
+
29
+ useEffect(() => {
30
+ setEditValue(value);
31
+ }, [value]);
32
+
33
+ useEffect(() => {
34
+ if (isEditing && inputRef.current) {
35
+ inputRef.current.focus();
36
+ inputRef.current.select();
37
+ }
38
+ }, [isEditing]);
39
+
40
+ useEffect(() => {
41
+ const handleClickOutside = (event: MouseEvent) => {
42
+ if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
43
+ if (isEditing) {
44
+ handleCancel();
45
+ }
46
+ }
47
+ };
48
+
49
+ document.addEventListener('mousedown', handleClickOutside);
50
+ return () => {
51
+ document.removeEventListener('mousedown', handleClickOutside);
52
+ };
53
+ }, [isEditing]);
54
+
55
+ const handleSave = () => {
56
+ if (editValue.trim()) {
57
+ onChange(editValue.trim());
58
+ setIsEditing(false);
59
+ }
60
+ };
61
+
62
+ const handleCancel = () => {
63
+ setEditValue(value);
64
+ setIsEditing(false);
65
+ };
66
+
67
+ const handleKeyDown = (e: React.KeyboardEvent) => {
68
+ if (e.key === 'Enter') {
69
+ handleSave();
70
+ } else if (e.key === 'Escape') {
71
+ handleCancel();
72
+ }
73
+ };
74
+
75
+ if (isEditing) {
76
+ return (
77
+ <div ref={containerRef} className={cn('flex items-center gap-2 max-w-md', className)}>
78
+ <Input
79
+ ref={inputRef}
80
+ value={editValue}
81
+ onChange={(e) => setEditValue(e.target.value)}
82
+ onKeyDown={handleKeyDown}
83
+ placeholder={placeholder}
84
+ className={cn('h-9', inputClassName)}
85
+ />
86
+ <Button size="icon" variant="ghost" className="h-9 w-9 shrink-0" onClick={handleSave}>
87
+ <Check className="w-4 h-4" />
88
+ </Button>
89
+ <Button size="icon" variant="ghost" className="h-9 w-9 shrink-0" onClick={handleCancel}>
90
+ <X className="w-4 h-4" />
91
+ </Button>
92
+ </div>
93
+ );
94
+ }
95
+
96
+ return (
97
+ <div ref={containerRef} className={cn('flex items-center gap-2 group', className)}>
98
+ <span className={cn('cursor-pointer', displayClassName)} onClick={() => setIsEditing(true)}>
99
+ {value || placeholder}
100
+ </span>
101
+ <Button
102
+ size="icon"
103
+ variant="ghost"
104
+ className="w-8 h-8 shrink-0"
105
+ onClick={() => setIsEditing(true)}
106
+ >
107
+ <Pencil className="w-4 h-4" />
108
+ </Button>
109
+ </div>
110
+ );
111
+ }
@@ -0,0 +1,334 @@
1
+ import { Label } from '../../ui/label';
2
+ import { Input } from '../../ui/input';
3
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
4
+ import { Switch } from '../../ui/switch';
5
+ import { Button } from '../../ui/button';
6
+ import { Code2, Type, AlertCircle } from 'lucide-react';
7
+ import type { NodeParamField } from '../../../types/node-definition.types';
8
+ import { cn } from '../../../lib/utils';
9
+ import { DroppableInput } from './DroppableInput';
10
+ import { DynamicSelectField } from './DynamicSelectField';
11
+ import { SearchableSelectField } from './SearchableSelectField';
12
+ import { CodeMirrorJsEditor } from '../../ui/codemirror-js-editor';
13
+ import { SwitchCasesField } from './SwitchCasesField';
14
+ import { useFlowEditorStore } from '../flow-editor.store';
15
+
16
+ interface ConfigFieldWithTemplateProps {
17
+ field: NodeParamField;
18
+ value: unknown;
19
+ onChange: (value: unknown) => void;
20
+ templateMode: boolean;
21
+ onTemplateModeChange: (enabled: boolean) => void;
22
+ portalContainer?: HTMLElement | null;
23
+ /** Action / node type id — needed for dynamic option loading. */
24
+ nodeType?: string;
25
+ /** All current form values — needed for dynamic option loading. */
26
+ formValues?: Record<string, unknown>;
27
+ /** Input data from upstream nodes — used for autocomplete in code fields. */
28
+ inputData?: Record<string, unknown>;
29
+ /** Validation error message for this field (from execution errors). */
30
+ error?: string;
31
+ }
32
+
33
+ /**
34
+ * Field types that are always in template mode (text-based inputs).
35
+ * These fields don't show a toggle - they always accept Nunjucks templates.
36
+ */
37
+ const ALWAYS_TEMPLATE_TYPES = ['text', 'textarea', 'json', 'code'];
38
+
39
+ /**
40
+ * Check if a field type should always be in template mode.
41
+ */
42
+ function isAlwaysTemplateType(fieldType: string): boolean {
43
+ return ALWAYS_TEMPLATE_TYPES.includes(fieldType);
44
+ }
45
+
46
+ /**
47
+ * A config field that supports toggling between static mode (normal form element)
48
+ * and template mode (Nunjucks template textarea).
49
+ *
50
+ * Text-based fields (text, textarea, json, code) are always in template mode.
51
+ * Other fields (select, number, boolean) show a toggle to switch between modes.
52
+ */
53
+ export const ConfigFieldWithTemplate = ({
54
+ field,
55
+ value,
56
+ onChange,
57
+ templateMode,
58
+ onTemplateModeChange,
59
+ portalContainer,
60
+ nodeType,
61
+ formValues,
62
+ inputData,
63
+ error,
64
+ }: ConfigFieldWithTemplateProps) => {
65
+ if (field.hidden) {
66
+ return null;
67
+ }
68
+
69
+ const fieldError = error ? (
70
+ <div className="flex items-center gap-1 text-[11px] text-destructive mt-0.5">
71
+ <AlertCircle className="w-3 h-3 shrink-0" />
72
+ <span>{error}</span>
73
+ </div>
74
+ ) : null;
75
+
76
+ // Switch cases: custom field with its own rendering
77
+ if (field.type === 'switch-cases') {
78
+ const selectedNodeId = useFlowEditorStore.getState().selectedNodeId;
79
+ return (
80
+ <SwitchCasesField
81
+ value={value}
82
+ onChange={onChange as (value: unknown) => void}
83
+ nodeId={selectedNodeId}
84
+ inputData={inputData}
85
+ />
86
+ );
87
+ }
88
+
89
+ // Check if this field type is always in template mode
90
+ const alwaysTemplate = isAlwaysTemplateType(field.type);
91
+ const effectiveTemplateMode = alwaysTemplate || templateMode;
92
+
93
+ const templateModeToggle = (
94
+ <Button
95
+ variant="ghost"
96
+ size="sm"
97
+ className={cn(
98
+ 'h-5 px-1.5 text-[10px] gap-0.5',
99
+ effectiveTemplateMode ? 'text-primary' : 'text-muted-foreground',
100
+ )}
101
+ onClick={() => onTemplateModeChange(!templateMode)}
102
+ title={effectiveTemplateMode ? 'Switch to static value' : 'Switch to template'}
103
+ >
104
+ {effectiveTemplateMode ? (
105
+ <>
106
+ <Code2 className="w-2.5 h-2.5" />
107
+ <span>Template</span>
108
+ </>
109
+ ) : (
110
+ <>
111
+ <Type className="w-2.5 h-2.5" />
112
+ <span>Static</span>
113
+ </>
114
+ )}
115
+ </Button>
116
+ );
117
+
118
+ // Header with or without toggle based on field type
119
+ const fieldHeader = (
120
+ <div className="flex items-center justify-between">
121
+ <Label htmlFor={field.name} className={cn('text-xs', error && 'text-destructive')}>
122
+ {field.label}
123
+ </Label>
124
+ {/* Only show toggle for non-text fields */}
125
+ {!alwaysTemplate && templateModeToggle}
126
+ </div>
127
+ );
128
+
129
+ // Code fields: render a JavaScript editor with syntax highlighting and autocomplete
130
+ if (field.type === 'code') {
131
+ const codeValue =
132
+ typeof value === 'string'
133
+ ? value
134
+ : value === null || value === undefined
135
+ ? ''
136
+ : typeof value === 'object'
137
+ ? JSON.stringify(value, null, 2)
138
+ : String(value);
139
+ return (
140
+ <div className="flex flex-col gap-1.5">
141
+ {fieldHeader}
142
+ <CodeMirrorJsEditor
143
+ value={codeValue}
144
+ onChange={(newValue) => onChange(newValue)}
145
+ placeholder={field.placeholder}
146
+ inputData={inputData}
147
+ />
148
+ {fieldError}
149
+ </div>
150
+ );
151
+ }
152
+
153
+ // Template mode: render a DroppableInput for Nunjucks templates
154
+ if (effectiveTemplateMode) {
155
+ // Determine if this should be multiline based on original field type
156
+ const isMultiline = field.type === 'textarea' || field.type === 'json';
157
+ const rows = field.type === 'json' ? 6 : field.type === 'textarea' ? 3 : 1;
158
+
159
+ return (
160
+ <div className={cn('flex flex-col gap-1.5', isMultiline && 'flex-1 min-h-0')}>
161
+ {fieldHeader}
162
+ <DroppableInput
163
+ id={field.name}
164
+ className={cn('text-xs font-mono', isMultiline && 'min-h-0 flex-1')}
165
+ multiline={isMultiline}
166
+ rows={rows}
167
+ fillAvailableHeight={isMultiline}
168
+ value={
169
+ typeof value === 'string'
170
+ ? value
171
+ : value === null || value === undefined
172
+ ? ''
173
+ : JSON.stringify(value, null, 2)
174
+ }
175
+ placeholder={field.placeholder || '{{ nodeId.data.variables.output.value }}'}
176
+ onChange={(newValue) => onChange(newValue)}
177
+ disabled={field.disabled}
178
+ />
179
+ {fieldError}
180
+ </div>
181
+ );
182
+ }
183
+
184
+ // Static mode: render the appropriate form element based on field type
185
+ // (Only reached for non-text fields when not in template mode)
186
+ switch (field.type) {
187
+ case 'select': {
188
+ // Dynamic options: delegate to DynamicSelectField when loadOptions is present
189
+ if (field.loadOptions && nodeType && formValues) {
190
+ return (
191
+ <div className="flex flex-col gap-1.5">
192
+ {fieldHeader}
193
+ <DynamicSelectField
194
+ actionId={nodeType}
195
+ field={field}
196
+ value={value}
197
+ onChange={onChange}
198
+ formValues={formValues}
199
+ portalContainer={portalContainer}
200
+ />
201
+ {fieldError}
202
+ </div>
203
+ );
204
+ }
205
+
206
+ const stringValue = value === undefined || value === null ? '' : String(value);
207
+ const optionEntries = (field.options ?? []).map((option) => ({
208
+ label: option.label,
209
+ value: String(option.value),
210
+ description: option.description,
211
+ }));
212
+ const hasCurrentValue = stringValue
213
+ ? optionEntries.some((option) => option.value === stringValue)
214
+ : false;
215
+ const renderOptions =
216
+ hasCurrentValue || !stringValue
217
+ ? optionEntries
218
+ : [{ label: stringValue, value: stringValue, description: undefined }, ...optionEntries];
219
+
220
+ const hasDescriptions = renderOptions.some((o) => o.description);
221
+
222
+ // Use searchable combobox for selects with many options (e.g. model lists)
223
+ const SEARCHABLE_THRESHOLD = 10;
224
+ if (renderOptions.length > SEARCHABLE_THRESHOLD) {
225
+ return (
226
+ <div className="flex flex-col gap-1.5">
227
+ {fieldHeader}
228
+ <SearchableSelectField
229
+ id={field.name}
230
+ value={stringValue}
231
+ options={renderOptions}
232
+ placeholder={field.placeholder}
233
+ disabled={field.disabled}
234
+ onChange={(val) => onChange(val)}
235
+ />
236
+ {fieldError}
237
+ </div>
238
+ );
239
+ }
240
+
241
+ return (
242
+ <div className="flex flex-col gap-1.5">
243
+ {fieldHeader}
244
+ <Select
245
+ value={stringValue}
246
+ onValueChange={(val) => onChange(val)}
247
+ disabled={field.disabled}
248
+ >
249
+ <SelectTrigger id={field.name} className="font-mono text-xs">
250
+ <SelectValue placeholder={field.placeholder} />
251
+ </SelectTrigger>
252
+ <SelectContent className="z-[80] text-xs" container={portalContainer}>
253
+ {renderOptions
254
+ .filter((option) => option.value !== '')
255
+ .map((option) => (
256
+ <SelectItem key={option.value} value={option.value}>
257
+ {hasDescriptions ? (
258
+ <div className="flex flex-col gap-0.5 py-0.5">
259
+ <span className="font-medium">{option.label}</span>
260
+ {option.description && (
261
+ <span className="text-[11px] text-muted-foreground font-normal leading-tight">
262
+ {option.description}
263
+ </span>
264
+ )}
265
+ </div>
266
+ ) : (
267
+ option.value
268
+ )}
269
+ </SelectItem>
270
+ ))}
271
+ </SelectContent>
272
+ </Select>
273
+ {fieldError}
274
+ </div>
275
+ );
276
+ }
277
+ case 'number':
278
+ return (
279
+ <div className="flex flex-col gap-1.5">
280
+ {fieldHeader}
281
+ <Input
282
+ id={field.name}
283
+ type="number"
284
+ className="h-8 font-mono text-xs"
285
+ value={value === undefined || value === null ? '' : String(value)}
286
+ placeholder={field.placeholder}
287
+ onChange={(event) => {
288
+ const nextValue = event.target.value;
289
+ onChange(nextValue === '' ? null : Number(nextValue));
290
+ }}
291
+ disabled={field.disabled}
292
+ />
293
+ {fieldError}
294
+ </div>
295
+ );
296
+ case 'boolean':
297
+ return (
298
+ <div className="flex flex-col gap-1.5">
299
+ {fieldHeader}
300
+ <div className="flex items-center gap-2 p-2 border rounded-md">
301
+ <Switch
302
+ id={field.name}
303
+ checked={Boolean(value)}
304
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
305
+ onChange(event.target.checked)
306
+ }
307
+ disabled={field.disabled}
308
+ />
309
+ <span className="text-xs">{value ? 'Enabled' : 'Disabled'}</span>
310
+ </div>
311
+ {fieldError}
312
+ </div>
313
+ );
314
+ case 'credential':
315
+ // Credential fields show a dropdown (handled separately in CredentialsSection)
316
+ // Fall through to default text input for now
317
+ default:
318
+ // Fallback for any other field types
319
+ return (
320
+ <div className="flex flex-col gap-1.5">
321
+ {fieldHeader}
322
+ <DroppableInput
323
+ id={field.name}
324
+ value={(value as string) ?? ''}
325
+ placeholder={field.placeholder}
326
+ onChange={(newValue) => onChange(newValue)}
327
+ disabled={field.disabled}
328
+ className="font-mono text-xs"
329
+ />
330
+ {fieldError}
331
+ </div>
332
+ );
333
+ }
334
+ };