@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,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
+ }