@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,298 @@
1
+ 'use client';
2
+
3
+ import { memo, useCallback, useState } from 'react';
4
+ import { Handle, Position, type NodeProps } from '@xyflow/react';
5
+ import { Card } from '../ui/card';
6
+ import { useNodeRegistry } from '../../contexts/NodeRegistryContext';
7
+ import { GraphNodeType, NodeExecutionStatus } from '@invect/core/types';
8
+ import { cn } from '../../lib/utils';
9
+ import { Loader2, Bot } from 'lucide-react';
10
+ import { NodeAppendix, type AppendixPosition } from './NodeAppendix';
11
+ import { AgentToolsBox } from './AgentToolsBox';
12
+ import type { ToolDefinition, AddedToolInstance } from './ToolSelectorModal';
13
+ import { useAgentToolCallbacks } from '../../contexts/AgentToolCallbacksContext';
14
+
15
+ // Stable style objects for Handles - avoids creating new objects on every render
16
+ const INPUT_HANDLE_STYLE = { top: '50%', transform: 'translate(-54%, -50%)' } as const;
17
+ const OUTPUT_HANDLE_STYLE_SINGLE = { top: '50%', transform: 'translate(54%, -50%)' } as const;
18
+ const OUTPUT_HANDLE_INNER_STYLE = { transform: 'translateX(54%)' } as const;
19
+ const HANDLE_CLASS =
20
+ '!bg-background !w-4 !h-4 !border-2 !border-muted-foreground !rounded-full !transition-colors hover:!bg-muted hover:!border-foreground !shadow-none !ring-0';
21
+
22
+ interface AgentNodeData extends Record<string, unknown> {
23
+ type?: GraphNodeType;
24
+ display_name?: string;
25
+ executionStatus?: NodeExecutionStatus;
26
+ params?: {
27
+ /** Added tool instances with their configurations */
28
+ addedTools?: AddedToolInstance[];
29
+ /** All available tools (populated by parent for tool resolution) */
30
+ availableTools?: ToolDefinition[];
31
+ toolsPosition?: AppendixPosition;
32
+ [key: string]: unknown;
33
+ };
34
+ // Event handlers (injected by FlowEditor)
35
+ /** Opens the tool selector modal */
36
+ onOpenToolSelector?: () => void;
37
+ /** Opens the tool selector modal with "show selected" filter enabled */
38
+ onShowMoreTools?: () => void;
39
+ /** Removes a tool instance from this node */
40
+ onRemoveTool?: (instanceId: string) => void;
41
+ /** Called when user clicks on a tool (to configure it) */
42
+ onToolClick?: (tool: AddedToolInstance) => void;
43
+ onToolsPositionChange?: (position: AppendixPosition) => void;
44
+ }
45
+
46
+ /**
47
+ * Loading placeholder shown while node definition is being fetched.
48
+ */
49
+ const AgentNodeLoadingPlaceholder = memo(
50
+ ({ data, selected }: { data: AgentNodeData; selected: boolean }) => {
51
+ const label = data.display_name || 'AI Agent';
52
+
53
+ return (
54
+ <Card
55
+ className={`relative w-[240px] h-[60px] flex-row py-0 items-center cursor-move transition-colors bg-card hover:bg-card/80 ${
56
+ selected
57
+ ? 'border-blue-500 dark:border-blue-400 shadow-lg shadow-blue-500/25 dark:shadow-blue-400/30'
58
+ : 'border-sidebar-ring hover:border-muted-foreground'
59
+ }`}
60
+ >
61
+ <Handle
62
+ id="input"
63
+ type="target"
64
+ position={Position.Left}
65
+ style={INPUT_HANDLE_STYLE}
66
+ className={HANDLE_CLASS}
67
+ />
68
+
69
+ <div className="flex items-center gap-3 px-3 py-0 overflow-hidden">
70
+ <div className="flex items-center justify-center w-10 h-10 shrink-0 rounded-xl bg-muted">
71
+ <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />
72
+ </div>
73
+ <div className="flex-1 min-w-0">
74
+ <div className="text-xs font-semibold tracking-tight truncate text-card-foreground">
75
+ {label}
76
+ </div>
77
+ <div className="font-mono text-xs tracking-tight truncate text-muted-foreground">
78
+ AGENT
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <Handle
84
+ id="output"
85
+ type="source"
86
+ position={Position.Right}
87
+ style={OUTPUT_HANDLE_STYLE_SINGLE}
88
+ className={HANDLE_CLASS}
89
+ />
90
+ </Card>
91
+ );
92
+ },
93
+ );
94
+
95
+ AgentNodeLoadingPlaceholder.displayName = 'AgentNodeLoadingPlaceholder';
96
+
97
+ /**
98
+ * AgentNode - A specialized node for AI Agents with an attached tools box
99
+ *
100
+ * This node renders like the UniversalNode but with an additional "appendix"
101
+ * panel that displays and manages the tools available to the agent.
102
+ */
103
+ export const AgentNode = memo(({ id, data, selected }: NodeProps) => {
104
+ const typedData = data as AgentNodeData;
105
+ const nodeType = GraphNodeType.AGENT;
106
+
107
+ const { getNodeDefinition, isLoading: registryLoading } = useNodeRegistry();
108
+ const definition = getNodeDefinition(nodeType);
109
+
110
+ // Read callbacks and available tools from context instead of data injection.
111
+ // This avoids the parent having to remap ALL nodes just to inject these into Agent data.
112
+ const toolCallbacks = useAgentToolCallbacks();
113
+
114
+ // Local state for tools position (can be controlled externally via data.params.toolsPosition)
115
+ const [localToolsPosition, setLocalToolsPosition] = useState<AppendixPosition>('bottom');
116
+ const toolsPosition = typedData.params?.toolsPosition ?? localToolsPosition;
117
+
118
+ // Available tools from context (provided by FlowEditor), falling back to data injection for non-editor views
119
+ const availableTools: ToolDefinition[] =
120
+ toolCallbacks?.availableTools ?? typedData.params?.availableTools ?? [];
121
+
122
+ // Get added tool instances from params
123
+ const addedTools: AddedToolInstance[] = typedData.params?.addedTools ?? [];
124
+
125
+ // Handle position change
126
+ const handlePositionChange = useCallback(
127
+ (position: AppendixPosition) => {
128
+ setLocalToolsPosition(position);
129
+ typedData.onToolsPositionChange?.(position);
130
+ },
131
+ [typedData],
132
+ );
133
+
134
+ // Show loading placeholder if registry is still loading or definition not found
135
+ if (registryLoading || !definition) {
136
+ return <AgentNodeLoadingPlaceholder data={typedData} selected={selected ?? false} />;
137
+ }
138
+
139
+ const label = typedData.display_name || definition.label || 'AI Agent';
140
+
141
+ // Agent nodes always use green/AI color
142
+ const iconColorClass = 'bg-green-500/15 text-green-600 dark:text-green-400';
143
+
144
+ // Get handle definitions from the node definition
145
+ const inputHandle = definition.input;
146
+ const outputs = definition.outputs || [];
147
+
148
+ const hasIncomingHandle = !!inputHandle;
149
+
150
+ // Check execution status for running state
151
+ const isRunning =
152
+ typedData.executionStatus === NodeExecutionStatus.RUNNING ||
153
+ typedData.executionStatus === NodeExecutionStatus.PENDING ||
154
+ typedData.executionStatus === NodeExecutionStatus.BATCH_SUBMITTED;
155
+ const isSuccess = typedData.executionStatus === NodeExecutionStatus.SUCCESS;
156
+ const isError = typedData.executionStatus === NodeExecutionStatus.FAILED;
157
+ const isSkipped = typedData.executionStatus === NodeExecutionStatus.SKIPPED;
158
+
159
+ const outputHandleConfigs = outputs.map((output, index) => {
160
+ if (outputs.length === 1) {
161
+ return { output, topPercent: 50 };
162
+ }
163
+ const EDGE_OFFSET = 28;
164
+ const availableSpace = 100 - EDGE_OFFSET * 2;
165
+ const topPercent = EDGE_OFFSET + (index / (outputs.length - 1)) * availableSpace;
166
+ return { output, topPercent };
167
+ });
168
+
169
+ // Compute border class for the tools appendix to match the node state
170
+ const appendixBorderClass = isRunning
171
+ ? 'border-primary'
172
+ : isSuccess
173
+ ? 'border-success'
174
+ : isError
175
+ ? 'border-destructive'
176
+ : isSkipped
177
+ ? 'border-dashed border-muted-foreground/50'
178
+ : selected
179
+ ? 'node-selected'
180
+ : 'border-sidebar-ring group-hover:border-primary/60';
181
+
182
+ return (
183
+ <div className="relative group">
184
+ {/* Main node card */}
185
+ <Card
186
+ className={cn(
187
+ 'relative w-[200px] h-[60px] flex-row py-0 items-center cursor-move transition-colors node-hover-bg bg-card',
188
+ // Default border
189
+ !isRunning &&
190
+ !isSuccess &&
191
+ !isError &&
192
+ !isSkipped &&
193
+ 'border-sidebar-ring group-hover:border-primary/60',
194
+ // Running state - animated gradient border
195
+ isRunning && 'node-running-border animate-node-border rounded-xl',
196
+ // Success state - green border
197
+ isSuccess && 'border-2 border-success',
198
+ // Error state - red border
199
+ isError && 'border-2 border-destructive',
200
+ // Skipped state - greyed out with dashed border
201
+ isSkipped && 'border-2 border-dashed border-muted-foreground/50 opacity-50',
202
+ // Selection state - change existing border color to blue for visibility
203
+ selected && !isRunning && !isSuccess && !isError && !isSkipped && 'node-selected',
204
+ )}
205
+ >
206
+ {/* Unified Input Handle */}
207
+ {hasIncomingHandle && (
208
+ <Handle
209
+ id={inputHandle?.id || 'input'}
210
+ type="target"
211
+ position={Position.Left}
212
+ style={INPUT_HANDLE_STYLE}
213
+ className={HANDLE_CLASS}
214
+ />
215
+ )}
216
+
217
+ <div className="flex items-center gap-3 px-3 py-0 overflow-hidden">
218
+ <div
219
+ className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ${iconColorClass}`}
220
+ >
221
+ <Bot className="w-6 h-6" />
222
+ </div>
223
+ <div className="flex-1 min-w-0">
224
+ <div className="text-xs font-semibold tracking-tight truncate text-card-foreground">
225
+ {label}
226
+ </div>
227
+ <div className="font-mono text-xs tracking-tight truncate text-muted-foreground">
228
+ {nodeType}
229
+ </div>
230
+ </div>
231
+ </div>
232
+
233
+ {/* Output Handles */}
234
+ {outputHandleConfigs.map(({ output, topPercent }) => {
235
+ const showLabel = outputs.length > 1;
236
+ return (
237
+ <div
238
+ key={output.id}
239
+ className="absolute right-0"
240
+ style={{ top: `${topPercent}%`, transform: 'translateY(-50%)' }}
241
+ >
242
+ <div className="relative flex items-center">
243
+ <Handle
244
+ id={output.id}
245
+ type="source"
246
+ position={Position.Right}
247
+ style={OUTPUT_HANDLE_INNER_STYLE}
248
+ className="!relative !bg-background !w-4 !h-4 !border-2 !border-muted-foreground !rounded-full !transition-colors hover:!bg-muted hover:!border-foreground !shadow-none !ring-0"
249
+ />
250
+ {showLabel && (
251
+ <div className="absolute px-1 text-xs border rounded left-8 text-card-foreground whitespace-nowrap bg-card border-sidebar-ring">
252
+ {output.label}
253
+ </div>
254
+ )}
255
+ </div>
256
+ </div>
257
+ );
258
+ })}
259
+ </Card>
260
+
261
+ {/* Tools Appendix - attached to the node */}
262
+ <NodeAppendix
263
+ position={toolsPosition}
264
+ onPositionChange={handlePositionChange}
265
+ showPositionToggle={true}
266
+ borderClassName={appendixBorderClass}
267
+ >
268
+ <AgentToolsBox
269
+ tools={addedTools}
270
+ availableTools={availableTools}
271
+ selectedInstanceId={
272
+ toolCallbacks?.selectedToolNodeId === id ? toolCallbacks.selectedToolInstanceId : null
273
+ }
274
+ onAddTool={
275
+ toolCallbacks
276
+ ? () => toolCallbacks.onOpenToolSelector(id)
277
+ : typedData.onOpenToolSelector
278
+ }
279
+ onShowMore={
280
+ toolCallbacks ? () => toolCallbacks.onShowMoreTools(id) : typedData.onShowMoreTools
281
+ }
282
+ onToolClick={
283
+ toolCallbacks
284
+ ? (tool: AddedToolInstance) => toolCallbacks.onToolClick(id, tool.instanceId)
285
+ : typedData.onToolClick
286
+ }
287
+ onRemoveTool={
288
+ toolCallbacks
289
+ ? (instanceId: string) => toolCallbacks.onRemoveTool(id, instanceId)
290
+ : typedData.onRemoveTool
291
+ }
292
+ />
293
+ </NodeAppendix>
294
+ </div>
295
+ );
296
+ });
297
+
298
+ AgentNode.displayName = 'AgentNode';
@@ -0,0 +1,193 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+ import { Plus, Settings } from 'lucide-react';
5
+ import { cn } from '../../lib/utils';
6
+ import { ProviderIcon } from '../shared/ProviderIcon';
7
+ import type { AddedToolInstance, ToolDefinition } from './ToolSelectorModal';
8
+
9
+ /**
10
+ * Tool category for organization in UI
11
+ * Matches AgentToolCategory from @invect/core
12
+ */
13
+ export type ToolCategory = 'data' | 'web' | 'code' | 'utility' | 'custom';
14
+
15
+ /**
16
+ * Simplified tool definition for display in the UI
17
+ * @deprecated Use AddedToolInstance instead
18
+ */
19
+ export interface AgentToolDisplay {
20
+ id: string;
21
+ name: string;
22
+ category: ToolCategory;
23
+ }
24
+
25
+ interface AgentToolsBoxProps {
26
+ /** Tool instances currently attached to the agent */
27
+ tools: AddedToolInstance[];
28
+ /** Available tool definitions for resolving category info */
29
+ availableTools: ToolDefinition[];
30
+ /** Currently selected tool instance ID (being configured) */
31
+ selectedInstanceId?: string | null;
32
+ /** Called when user clicks "Add Tool" button */
33
+ onAddTool?: () => void;
34
+ /** Called when user wants to see all selected tools (opens modal with filter) */
35
+ onShowMore?: () => void;
36
+ /** Called when user clicks on a tool (to configure it) */
37
+ onToolClick?: (tool: AddedToolInstance) => void;
38
+ /** Called when user clicks remove button on a tool */
39
+ onRemoveTool?: (instanceId: string) => void;
40
+ /** Additional CSS classes */
41
+ className?: string;
42
+ }
43
+
44
+ // Maximum visible tools in grid (2 columns x 3 rows)
45
+ const MAX_VISIBLE_TOOLS = 6;
46
+
47
+ /**
48
+ * ToolTile - Compact square tile for displaying a tool in the grid
49
+ */
50
+ const ToolTile = memo(function ToolTile({
51
+ tool,
52
+ toolDef,
53
+ isSelected,
54
+ onToolClick,
55
+ onRemoveTool: _onRemoveTool,
56
+ }: {
57
+ tool: AddedToolInstance;
58
+ toolDef: ToolDefinition | undefined;
59
+ isSelected?: boolean;
60
+ onToolClick?: (tool: AddedToolInstance) => void;
61
+ onRemoveTool?: (instanceId: string) => void;
62
+ }) {
63
+ return (
64
+ <div
65
+ className={cn(
66
+ 'group relative flex flex-row items-center p-1 gap-1 rounded-md border cursor-pointer transition-colors w-[99px]',
67
+ 'hover:bg-accent hover:border-accent-foreground/20',
68
+ isSelected && 'bg-accent border-primary ring-1 ring-primary/30',
69
+ )}
70
+ onClick={() => onToolClick?.(tool)}
71
+ title={tool.name}
72
+ >
73
+ {toolDef?.provider?.svgIcon || toolDef?.provider?.icon || toolDef?.provider?.id ? (
74
+ <ProviderIcon
75
+ providerId={toolDef?.provider?.id}
76
+ svgIcon={toolDef?.provider?.svgIcon}
77
+ icon={toolDef?.provider?.icon}
78
+ className="w-5 h-5 shrink-0"
79
+ />
80
+ ) : null}
81
+ <span className="text-[10px] truncate w-full">{tool.name}</span>
82
+ </div>
83
+ );
84
+ });
85
+
86
+ /**
87
+ * AgentToolsBox - Displays and manages tools attached to an AI Agent node
88
+ *
89
+ * Renders as a compact grid showing tool tiles with category-based styling.
90
+ * Shows max 2x3 grid with "show more" button if there are more tools.
91
+ */
92
+ export const AgentToolsBox = memo(function AgentToolsBox({
93
+ tools,
94
+ availableTools,
95
+ selectedInstanceId,
96
+ onAddTool,
97
+ onShowMore,
98
+ onToolClick,
99
+ onRemoveTool,
100
+ className,
101
+ }: AgentToolsBoxProps) {
102
+ const isEmpty = tools.length === 0;
103
+ const hasMoreTools = tools.length > MAX_VISIBLE_TOOLS;
104
+ const visibleTools = hasMoreTools ? tools.slice(0, MAX_VISIBLE_TOOLS - 1) : tools;
105
+ const hiddenCount = tools.length - visibleTools.length;
106
+
107
+ // Helper to get tool definition by toolId
108
+ const getToolDef = (toolId: string) => availableTools.find((t) => t.id === toolId);
109
+
110
+ return (
111
+ <div className={cn('w-[220px] p-2', className)}>
112
+ {/* Header - only show if we have tools */}
113
+ {!isEmpty && (
114
+ <div className="mb-2 text-xs font-medium text-muted-foreground">Tools ({tools.length})</div>
115
+ )}
116
+
117
+ {isEmpty ? (
118
+ /* Empty state - prominent add button */
119
+ onAddTool && (
120
+ <button
121
+ onClick={(e) => {
122
+ e.stopPropagation();
123
+ e.preventDefault();
124
+ onAddTool();
125
+ }}
126
+ className="flex flex-col items-center justify-center w-full gap-2 p-4 transition-all border-2 border-dashed rounded-lg border-muted-foreground/30 text-muted-foreground hover:border-primary/50 hover:text-primary hover:bg-primary/5"
127
+ >
128
+ <div className="flex items-center justify-center w-10 h-10 rounded-full bg-muted">
129
+ <Plus className="w-5 h-5" />
130
+ </div>
131
+ <div className="text-center">
132
+ <div className="text-xs font-medium">Add Tools</div>
133
+ <div className="text-[10px] opacity-70">Give the agent capabilities</div>
134
+ </div>
135
+ </button>
136
+ )
137
+ ) : (
138
+ /* Tools grid */
139
+ <div className="space-y-2">
140
+ <div className="grid grid-cols-2 gap-1.5">
141
+ {visibleTools.map((tool) => (
142
+ <ToolTile
143
+ key={tool.instanceId}
144
+ tool={tool}
145
+ toolDef={getToolDef(tool.toolId)}
146
+ isSelected={selectedInstanceId === tool.instanceId}
147
+ onToolClick={onToolClick}
148
+ onRemoveTool={onRemoveTool}
149
+ />
150
+ ))}
151
+
152
+ {/* Show more button - takes place of last tile when there are more tools */}
153
+ {hasMoreTools && (
154
+ <button
155
+ onClick={(e) => {
156
+ e.stopPropagation();
157
+ e.preventDefault();
158
+ onShowMore?.();
159
+ }}
160
+ className="flex items-center justify-center transition-colors border border-dashed rounded-md cursor-pointer border-muted-foreground/50 text-muted-foreground hover:border-primary hover:text-primary hover:bg-primary/5"
161
+ title={`Show ${hiddenCount} more tools`}
162
+ >
163
+ <span className="text-[10px]">+{hiddenCount} more</span>
164
+ </button>
165
+ )}
166
+ </div>
167
+
168
+ {/* Configure button */}
169
+ {onAddTool && (
170
+ <button
171
+ onClick={(e) => {
172
+ e.stopPropagation();
173
+ e.preventDefault();
174
+ onAddTool();
175
+ }}
176
+ className="flex items-center justify-center gap-1.5 rounded-md border border-dashed border-muted-foreground/50 px-2 py-1.5 text-xs text-muted-foreground hover:border-muted-foreground hover:text-foreground transition-colors w-full"
177
+ >
178
+ <Settings className="w-3 h-3" />
179
+ <span>Configure</span>
180
+ </button>
181
+ )}
182
+ </div>
183
+ )}
184
+
185
+ {/* Empty state - only show if no add button */}
186
+ {isEmpty && !onAddTool && (
187
+ <div className="text-xs italic text-muted-foreground/60">No tools configured</div>
188
+ )}
189
+ </div>
190
+ );
191
+ });
192
+
193
+ AgentToolsBox.displayName = 'AgentToolsBox';
@@ -0,0 +1,98 @@
1
+ import { memo } from 'react';
2
+ import { MoveVertical, MoveHorizontal } from 'lucide-react';
3
+ import { cn } from '../../lib/utils';
4
+
5
+ export type AppendixPosition = 'top' | 'bottom' | 'left' | 'right';
6
+
7
+ interface NodeAppendixProps {
8
+ position?: AppendixPosition;
9
+ onPositionChange?: (position: AppendixPosition) => void;
10
+ children: React.ReactNode;
11
+ className?: string;
12
+ /** Override the default border class (e.g. for selected/hover/state colours) */
13
+ borderClassName?: string;
14
+ /** Whether to show the position toggle button */
15
+ showPositionToggle?: boolean;
16
+ }
17
+
18
+ const positionClasses: Record<AppendixPosition, string> = {
19
+ top: 'bottom-full left-1/2 -translate-x-1/2 mb-2 flex-col-reverse',
20
+ bottom: 'top-full left-1/2 -translate-x-1/2 mt-2 flex-col',
21
+ left: 'right-full top-1/2 -translate-y-1/2 mr-2 flex-row-reverse',
22
+ right: 'left-full top-1/2 -translate-y-1/2 ml-2 flex-row',
23
+ };
24
+
25
+ const connectorClasses: Record<AppendixPosition, string> = {
26
+ top: 'w-px h-2 mx-auto',
27
+ bottom: 'w-px h-2 mx-auto',
28
+ left: 'h-px w-2 my-auto',
29
+ right: 'h-px w-2 my-auto',
30
+ };
31
+
32
+ const positionCycle: AppendixPosition[] = ['bottom', 'right', 'top', 'left'];
33
+
34
+ /**
35
+ * NodeAppendix - A reusable component that renders an attached panel to a node
36
+ *
37
+ * Used to display additional content like tools, configurations, or previews
38
+ * that are visually connected to a node but rendered outside its bounds.
39
+ */
40
+ export const NodeAppendix = memo(function NodeAppendix({
41
+ position = 'bottom',
42
+ onPositionChange,
43
+ children,
44
+ className,
45
+ borderClassName,
46
+ showPositionToggle = true,
47
+ }: NodeAppendixProps) {
48
+ const handlePositionToggle = () => {
49
+ if (!onPositionChange) {
50
+ return;
51
+ }
52
+ const currentIndex = positionCycle.indexOf(position);
53
+ const nextIndex = (currentIndex + 1) % positionCycle.length;
54
+ onPositionChange(positionCycle[nextIndex]);
55
+ };
56
+
57
+ const isVertical = position === 'top' || position === 'bottom';
58
+ const ToggleIcon = isVertical ? MoveVertical : MoveHorizontal;
59
+
60
+ const resolvedBorderClass = borderClassName || 'border-sidebar-ring';
61
+
62
+ return (
63
+ <div className={cn('absolute flex items-center nowheel nopan', positionClasses[position])}>
64
+ {/* Connector line */}
65
+ <div className={cn('bg-sidebar-ring', connectorClasses[position])} />
66
+
67
+ {/* Content container */}
68
+ <div
69
+ className={cn(
70
+ 'relative rounded-lg border bg-card shadow-md nodrag transition-colors',
71
+ resolvedBorderClass,
72
+ className,
73
+ )}
74
+ >
75
+ {/* Position toggle button */}
76
+ {showPositionToggle && onPositionChange && (
77
+ <button
78
+ onClick={(e) => {
79
+ e.stopPropagation();
80
+ handlePositionToggle();
81
+ }}
82
+ className={cn(
83
+ 'absolute z-10 flex items-center justify-center w-5 h-5 transition-colors border rounded-full -top-2 -right-2 bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground',
84
+ resolvedBorderClass,
85
+ )}
86
+ title="Change position"
87
+ >
88
+ <ToggleIcon className="w-3 h-3" />
89
+ </button>
90
+ )}
91
+
92
+ {children}
93
+ </div>
94
+ </div>
95
+ );
96
+ });
97
+
98
+ NodeAppendix.displayName = 'NodeAppendix';
@@ -0,0 +1,74 @@
1
+ import React from 'react';
2
+ import { cn } from '../../lib/utils';
3
+
4
+ export type NodeStatusIndicatorStatus = 'initial' | 'loading' | 'success' | 'error';
5
+ export type NodeStatusIndicatorLoadingVariant = 'border' | 'overlay';
6
+
7
+ interface NodeStatusIndicatorProps {
8
+ status: NodeStatusIndicatorStatus;
9
+ loadingVariant?: NodeStatusIndicatorLoadingVariant;
10
+ children: React.ReactNode;
11
+ className?: string;
12
+ }
13
+
14
+ /**
15
+ * A node wrapper that indicates the status of a node via a border effect.
16
+ *
17
+ * Status can be:
18
+ * - "initial" - no status indicator (default state)
19
+ * - "loading" - animated conic gradient border that rotates
20
+ * - "success" - green border
21
+ * - "error" - red border
22
+ *
23
+ * Loading variants:
24
+ * - "border" - animated gradient border around the node (default)
25
+ * - "overlay" - full overlay with spinner
26
+ *
27
+ * The animated border uses CSS @property for the conic gradient angle animation.
28
+ * This is supported in Chrome/Chromium browsers. Firefox will show a static gradient.
29
+ */
30
+ export function NodeStatusIndicator({
31
+ status,
32
+ loadingVariant = 'border',
33
+ children,
34
+ className,
35
+ }: NodeStatusIndicatorProps) {
36
+ // For initial status, just render children without any wrapper styling
37
+ if (status === 'initial') {
38
+ return <div className={className}>{children}</div>;
39
+ }
40
+
41
+ const isLoading = status === 'loading';
42
+ const isSuccess = status === 'success';
43
+ const isError = status === 'error';
44
+
45
+ return (
46
+ <div className={cn('relative node-status-active', className)}>
47
+ {/* Status border wrapper */}
48
+ <div
49
+ className={cn(
50
+ 'relative rounded-xl',
51
+ // Success state - static green border
52
+ isSuccess && 'ring-2 ring-green-500 ring-offset-0 ring-offset-background',
53
+ // Error state - static red border
54
+ isError && 'ring-2 ring-red-500 ring-offset-0 ring-offset-background',
55
+ // Loading state with border variant - animated gradient border using CSS @property
56
+ isLoading &&
57
+ loadingVariant === 'border' &&
58
+ 'node-running-border rounded-xl border border-transparent animate-node-border',
59
+ )}
60
+ >
61
+ {children}
62
+ </div>
63
+
64
+ {/* Loading overlay variant */}
65
+ {isLoading && loadingVariant === 'overlay' && (
66
+ <div className="absolute inset-0 flex items-center justify-center rounded-lg bg-background/60 backdrop-blur-[1px]">
67
+ <div className="w-6 h-6 border-2 rounded-full border-t-transparent border-primary animate-spin" />
68
+ </div>
69
+ )}
70
+ </div>
71
+ );
72
+ }
73
+
74
+ NodeStatusIndicator.displayName = 'NodeStatusIndicator';