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