@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,208 @@
1
+ /**
2
+ * ChatModelSelector — Combobox for selecting the LLM model in the chat input area.
3
+ *
4
+ * Shows models from the provider's API (server-filtered with debounced search),
5
+ * with a "Recent" section for recently used models tracked via localStorage.
6
+ */
7
+
8
+ import React, { useState, useCallback, useMemo, useEffect } from 'react';
9
+ import { Check, ChevronsUpDown, Clock, Loader2, Sparkles } from 'lucide-react';
10
+ import { useQuery } from '@tanstack/react-query';
11
+ import { cn } from '~/lib/utils';
12
+ import { Button } from '~/components/ui/button';
13
+ import { Popover, PopoverContent, PopoverTrigger } from '~/components/ui/popover';
14
+ import {
15
+ Command,
16
+ CommandEmpty,
17
+ CommandGroup,
18
+ CommandInput,
19
+ CommandItem,
20
+ CommandList,
21
+ } from '~/components/ui/command';
22
+ import { useApiClient } from '~/contexts/ApiContext';
23
+ import { useChatStore } from './chat.store';
24
+
25
+ const MAX_RECENT_MODELS = 5;
26
+ const DEBOUNCE_MS = 300;
27
+
28
+ function useDebouncedValue<T>(value: T, delayMs: number): T {
29
+ const [debounced, setDebounced] = useState(value);
30
+ useEffect(() => {
31
+ const timer = setTimeout(() => setDebounced(value), delayMs);
32
+ return () => clearTimeout(timer);
33
+ }, [value, delayMs]);
34
+ return debounced;
35
+ }
36
+
37
+ interface ChatModelSelectorProps {
38
+ className?: string;
39
+ }
40
+
41
+ export function ChatModelSelector({ className }: ChatModelSelectorProps) {
42
+ const [open, setOpen] = useState(false);
43
+ const [search, setSearch] = useState('');
44
+ const debouncedSearch = useDebouncedValue(search, DEBOUNCE_MS);
45
+ const apiClient = useApiClient();
46
+
47
+ const credentialId = useChatStore((s) => s.settings.credentialId);
48
+ const selectedModel = useChatStore((s) => s.settings.model);
49
+ const recentModels = useChatStore((s) => s.settings.recentModels);
50
+ const updateSettings = useChatStore((s) => s.updateSettings);
51
+
52
+ // Fetch models with server-side search filter
53
+ const {
54
+ data: models = [],
55
+ isLoading,
56
+ isError,
57
+ isFetching,
58
+ } = useQuery({
59
+ queryKey: ['chat-models', credentialId, debouncedSearch],
60
+ queryFn: () => apiClient.getChatModels(credentialId ?? '', debouncedSearch || undefined),
61
+ enabled: !!credentialId && open,
62
+ staleTime: 5 * 60 * 1000, // 5 min cache per query
63
+ retry: 1,
64
+ });
65
+
66
+ // Reset search when popover closes
67
+ useEffect(() => {
68
+ if (!open) {
69
+ setSearch('');
70
+ }
71
+ }, [open]);
72
+
73
+ const handleSelect = useCallback(
74
+ (modelId: string) => {
75
+ const newRecents = [modelId, ...recentModels.filter((id) => id !== modelId)].slice(
76
+ 0,
77
+ MAX_RECENT_MODELS,
78
+ );
79
+ updateSettings({ model: modelId, recentModels: newRecents });
80
+ setOpen(false);
81
+ },
82
+ [recentModels, updateSettings],
83
+ );
84
+
85
+ // Recent models (only shown when not searching)
86
+ const recentModelItems = useMemo(() => {
87
+ if (debouncedSearch || !recentModels.length || !models.length) {
88
+ return [];
89
+ }
90
+ return recentModels
91
+ .map((id) => models.find((m) => m.id === id))
92
+ .filter((m): m is NonNullable<typeof m> => m !== null && m !== undefined);
93
+ }, [debouncedSearch, recentModels, models]);
94
+
95
+ const displayLabel = useMemo(() => {
96
+ if (!selectedModel) {
97
+ return 'Default model';
98
+ }
99
+ return selectedModel;
100
+ }, [selectedModel]);
101
+
102
+ if (!credentialId) {
103
+ return null;
104
+ }
105
+
106
+ const showSpinner = isFetching && debouncedSearch !== search;
107
+
108
+ return (
109
+ <Popover open={open} onOpenChange={setOpen}>
110
+ <PopoverTrigger asChild>
111
+ <Button
112
+ variant="ghost"
113
+ size="sm"
114
+ role="combobox"
115
+ aria-expanded={open}
116
+ className={cn(
117
+ 'h-6 gap-1 px-2 text-[11px] font-normal text-muted-foreground hover:text-foreground max-w-50',
118
+ className,
119
+ )}
120
+ >
121
+ <Sparkles className="size-3 shrink-0" />
122
+ <span className="truncate">{displayLabel}</span>
123
+ <ChevronsUpDown className="ml-auto size-3 shrink-0 opacity-50" />
124
+ </Button>
125
+ </PopoverTrigger>
126
+ <PopoverContent className="w-70 p-0" align="start" side="top" sideOffset={8}>
127
+ <Command shouldFilter={false}>
128
+ <div className="relative">
129
+ <CommandInput
130
+ placeholder="Search models…"
131
+ className="h-8 text-xs focus:ring-0 focus:outline-none"
132
+ value={search}
133
+ onValueChange={setSearch}
134
+ />
135
+ {showSpinner && (
136
+ <Loader2 className="absolute size-3 animate-spin right-2 top-2.5 text-muted-foreground" />
137
+ )}
138
+ </div>
139
+ <CommandList className="max-h-62.5">
140
+ {isLoading && (
141
+ <div className="py-4 text-xs text-center text-muted-foreground">Loading models…</div>
142
+ )}
143
+ {isError && (
144
+ <div className="py-4 text-xs text-center text-muted-foreground">
145
+ Failed to load models
146
+ </div>
147
+ )}
148
+ {!isLoading && !isError && models.length === 0 && debouncedSearch && (
149
+ <CommandEmpty>No models matching &ldquo;{debouncedSearch}&rdquo;</CommandEmpty>
150
+ )}
151
+
152
+ {/* Default option (only when not searching) */}
153
+ {!debouncedSearch && (
154
+ <CommandGroup>
155
+ <CommandItem
156
+ value="__default__"
157
+ onSelect={() => {
158
+ updateSettings({ model: null });
159
+ setOpen(false);
160
+ }}
161
+ className="text-xs"
162
+ >
163
+ <span className="text-muted-foreground">Provider default</span>
164
+ {!selectedModel && <Check className="ml-auto size-3" />}
165
+ </CommandItem>
166
+ </CommandGroup>
167
+ )}
168
+
169
+ {/* Recent models (only when not searching) */}
170
+ {recentModelItems.length > 0 && (
171
+ <CommandGroup heading="Recent">
172
+ {recentModelItems.map((model) => (
173
+ <CommandItem
174
+ key={`recent-${model.id}`}
175
+ value={`recent-${model.id}`}
176
+ onSelect={() => handleSelect(model.id)}
177
+ className="text-xs"
178
+ >
179
+ <Clock className="mr-1.5 size-3 text-muted-foreground/60" />
180
+ <span className="truncate">{model.name || model.id}</span>
181
+ {selectedModel === model.id && <Check className="ml-auto size-3" />}
182
+ </CommandItem>
183
+ ))}
184
+ </CommandGroup>
185
+ )}
186
+
187
+ {/* All / filtered models */}
188
+ {models.length > 0 && (
189
+ <CommandGroup heading={debouncedSearch ? 'Results' : 'All models'}>
190
+ {models.map((model) => (
191
+ <CommandItem
192
+ key={model.id}
193
+ value={model.id}
194
+ onSelect={() => handleSelect(model.id)}
195
+ className="text-xs"
196
+ >
197
+ <span className="truncate">{model.name || model.id}</span>
198
+ {selectedModel === model.id && <Check className="ml-auto size-3" />}
199
+ </CommandItem>
200
+ ))}
201
+ </CommandGroup>
202
+ )}
203
+ </CommandList>
204
+ </Command>
205
+ </PopoverContent>
206
+ </Popover>
207
+ );
208
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * ChatPanel — Main chat assistant sidebar component.
3
+ *
4
+ * Slim composition shell that wires up hooks and composes
5
+ * ChatMessageList, ChatInput, and ChatSettingsPanel.
6
+ */
7
+
8
+ import React, { useRef, useEffect, useCallback, useMemo } from 'react';
9
+ import { MessageSquare, X, Trash2, Bot, Settings2 } from 'lucide-react';
10
+ import { cn } from '~/lib/utils';
11
+ import { Button } from '~/components/ui/button';
12
+ import { Tooltip, TooltipTrigger, TooltipContent } from '~/components/ui/tooltip';
13
+ import { useChat } from './use-chat';
14
+ import { useCredentials } from '~/api/credentials.api';
15
+ import { useChatStore } from './chat.store';
16
+ import { ChatSettingsPanel } from './ChatSettingsPanel';
17
+ import { ChatMessageList } from './ChatMessageList';
18
+ import { ChatInput } from './ChatInput';
19
+ import { useToolbarCollapsed } from '~/components/flow-editor/toolbar-context';
20
+
21
+ const DEFAULT_WIDTH = 440;
22
+ const MIN_WIDTH = 340;
23
+ const MAX_WIDTH = 700;
24
+
25
+ // =====================================
26
+ // ChatPanel (main export)
27
+ // =====================================
28
+
29
+ interface ChatPanelProps {
30
+ flowId?: string;
31
+ selectedNodeId?: string;
32
+ selectedRunId?: string;
33
+ viewMode?: 'edit' | 'runs';
34
+ basePath?: string;
35
+ className?: string;
36
+ }
37
+
38
+ export function ChatPanel({
39
+ flowId,
40
+ selectedNodeId,
41
+ selectedRunId,
42
+ viewMode,
43
+ basePath,
44
+ className,
45
+ }: ChatPanelProps) {
46
+ const {
47
+ sendMessage,
48
+ stopStreaming,
49
+ clearMessages,
50
+ messages,
51
+ isStreaming,
52
+ isLoadingHistory,
53
+ streamingText,
54
+ error,
55
+ isOpen,
56
+ setOpen,
57
+ isSettingsPanelOpen,
58
+ toggleSettingsPanel,
59
+ } = useChat({ flowId, selectedNodeId, selectedRunId, viewMode: viewMode ?? 'edit', basePath });
60
+
61
+ // Check if a credential has been selected for the chat assistant
62
+ const credentialId = useChatStore((s) => s.settings.credentialId);
63
+ const { data: llmCredentials = [], isLoading: isLoadingCredentials } = useCredentials({
64
+ type: 'llm',
65
+ isActive: true,
66
+ });
67
+ const hasAvailableLlmCredentials = llmCredentials.length > 0;
68
+ const hasSelectedCredential = useMemo(
69
+ () =>
70
+ Boolean(credentialId && llmCredentials.some((credential) => credential.id === credentialId)),
71
+ [credentialId, llmCredentials],
72
+ );
73
+ const hasConfiguredCredential = credentialId
74
+ ? isLoadingCredentials || hasSelectedCredential
75
+ : false;
76
+
77
+ // Consume pending prompt from overlay (fires once when panel opens with a queued prompt)
78
+ const pendingConsumed = useRef(false);
79
+ useEffect(() => {
80
+ if (!isOpen || isStreaming || pendingConsumed.current || !hasConfiguredCredential) {
81
+ return;
82
+ }
83
+ const prompt = useChatStore.getState().consumePendingPrompt();
84
+ if (prompt) {
85
+ pendingConsumed.current = true;
86
+ setTimeout(() => {
87
+ sendMessage(prompt);
88
+ pendingConsumed.current = false;
89
+ }, 50);
90
+ }
91
+ }, [hasConfiguredCredential, isOpen, isStreaming, sendMessage]);
92
+
93
+ // --- Resize logic ---
94
+ const [panelWidth, setPanelWidth] = React.useState(DEFAULT_WIDTH);
95
+ const isResizing = useRef(false);
96
+
97
+ const startResize = useCallback(
98
+ (e: React.MouseEvent) => {
99
+ e.preventDefault();
100
+ isResizing.current = true;
101
+ const startX = e.clientX;
102
+ const startWidth = panelWidth;
103
+
104
+ const onMouseMove = (ev: MouseEvent) => {
105
+ if (!isResizing.current) {
106
+ return;
107
+ }
108
+ const delta = startX - ev.clientX;
109
+ const next = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startWidth + delta));
110
+ setPanelWidth(next);
111
+ };
112
+
113
+ const onMouseUp = () => {
114
+ isResizing.current = false;
115
+ document.removeEventListener('mousemove', onMouseMove);
116
+ document.removeEventListener('mouseup', onMouseUp);
117
+ document.body.style.cursor = '';
118
+ document.body.style.userSelect = '';
119
+ };
120
+
121
+ document.body.style.cursor = 'col-resize';
122
+ document.body.style.userSelect = 'none';
123
+ document.addEventListener('mousemove', onMouseMove);
124
+ document.addEventListener('mouseup', onMouseUp);
125
+ },
126
+ [panelWidth],
127
+ );
128
+
129
+ if (!isOpen) {
130
+ return null;
131
+ }
132
+
133
+ return (
134
+ <div
135
+ className={cn(
136
+ 'relative flex flex-col h-full border-l border-border bg-imp-background text-card-foreground',
137
+ className,
138
+ )}
139
+ style={{ width: panelWidth, minWidth: MIN_WIDTH, maxWidth: MAX_WIDTH }}
140
+ >
141
+ {/* Resize handle on left edge */}
142
+ <div
143
+ onMouseDown={startResize}
144
+ className="absolute inset-y-0 left-0 z-20 w-1 transition-colors cursor-col-resize hover:bg-primary/20 active:bg-primary/30"
145
+ />
146
+ {/* Header */}
147
+ <div className="flex items-center justify-between px-4 py-2.5 border-b border-border">
148
+ <div className="flex items-center gap-2">
149
+ <Bot className="size-4 text-primary" />
150
+ <span className="text-sm font-semibold">Chat</span>
151
+ </div>
152
+ <div className="flex items-center gap-1.5">
153
+ <Button
154
+ variant={isSettingsPanelOpen ? 'secondary' : 'ghost'}
155
+ size="icon-sm"
156
+ onClick={toggleSettingsPanel}
157
+ title="Chat settings"
158
+ >
159
+ <Settings2 className="size-3.5" />
160
+ </Button>
161
+ <Button
162
+ variant="ghost"
163
+ size="icon-sm"
164
+ onClick={clearMessages}
165
+ title="Clear chat"
166
+ disabled={isStreaming || messages.length === 0}
167
+ >
168
+ <Trash2 className="size-3.5" />
169
+ </Button>
170
+ <Button variant="ghost" size="icon-sm" onClick={() => setOpen(false)} title="Close">
171
+ <X className="size-4" />
172
+ </Button>
173
+ </div>
174
+ </div>
175
+
176
+ {/* Settings Panel (slide-over) */}
177
+ {isSettingsPanelOpen && (
178
+ <div className="absolute inset-0 z-30 flex flex-col bg-imp-background">
179
+ <ChatSettingsPanel onClose={toggleSettingsPanel} />
180
+ </div>
181
+ )}
182
+
183
+ {/* Messages */}
184
+ <ChatMessageList
185
+ messages={messages}
186
+ isStreaming={isStreaming}
187
+ isLoadingHistory={isLoadingHistory}
188
+ streamingText={streamingText}
189
+ error={error}
190
+ hasConfiguredCredential={hasConfiguredCredential}
191
+ hasAvailableLlmCredentials={hasAvailableLlmCredentials}
192
+ onOpenSettings={toggleSettingsPanel}
193
+ onSendMessage={sendMessage}
194
+ />
195
+
196
+ {/* Input */}
197
+ <ChatInput
198
+ isStreaming={isStreaming}
199
+ isLoadingHistory={isLoadingHistory}
200
+ hasConfiguredCredential={hasConfiguredCredential}
201
+ hasAvailableLlmCredentials={hasAvailableLlmCredentials}
202
+ onSend={sendMessage}
203
+ onStop={stopStreaming}
204
+ onOpenSettings={toggleSettingsPanel}
205
+ />
206
+ </div>
207
+ );
208
+ }
209
+
210
+ // =====================================
211
+ // ChatToggleButton (for toolbar)
212
+ // =====================================
213
+
214
+ export function ChatToggleButton({ className }: { className?: string }) {
215
+ const { isOpen, togglePanel } = useChat();
216
+ const collapsed = useToolbarCollapsed();
217
+
218
+ return (
219
+ <Tooltip>
220
+ <TooltipTrigger asChild>
221
+ <Button
222
+ variant="ghost"
223
+ size="sm"
224
+ onClick={togglePanel}
225
+ title={collapsed ? undefined : isOpen ? 'Close AI Chat' : 'Open AI Chat'}
226
+ className={cn(
227
+ 'gap-1.5 hover:bg-accent',
228
+ isOpen
229
+ ? 'bg-accent text-accent-foreground'
230
+ : 'text-muted-foreground hover:text-foreground',
231
+ className,
232
+ )}
233
+ >
234
+ <MessageSquare className="size-4" />
235
+ {!collapsed && <span className="text-xs font-medium">Chat</span>}
236
+ </Button>
237
+ </TooltipTrigger>
238
+ {collapsed && (
239
+ <TooltipContent side="top">{isOpen ? 'Close AI Chat' : 'Open AI Chat'}</TooltipContent>
240
+ )}
241
+ </Tooltip>
242
+ );
243
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * ChatPromptOverlay — Centered empty-flow prompt.
3
+ *
4
+ * Appears in the center of the flow editor viewport when the flow
5
+ * has no nodes. Shows an "Add Node" button, an "or" separator,
6
+ * and a chat input encouraging users to describe what they need.
7
+ * On submit, opens the full ChatPanel and sends the prompt.
8
+ */
9
+
10
+ import React, { useState, useCallback, useRef, useEffect } from 'react';
11
+ import { Plus, ArrowUp } from 'lucide-react';
12
+ import { cn } from '~/lib/utils';
13
+ import { useChatStore, useChatOpen } from './chat.store';
14
+ import { useNodes } from '~/stores/flow-editor.store';
15
+ import { useUIStore } from '~/stores/uiStore';
16
+
17
+ interface ChatPromptOverlayProps {
18
+ className?: string;
19
+ }
20
+
21
+ export function ChatPromptOverlay({ className }: ChatPromptOverlayProps) {
22
+ const [value, setValue] = useState('');
23
+ const [focused, setFocused] = useState(false);
24
+ const inputRef = useRef<HTMLTextAreaElement>(null);
25
+
26
+ const nodes = useNodes();
27
+ const isChatOpen = useChatOpen();
28
+ const setNodeSidebarOpen = useUIStore((s) => s.setNodeSidebarOpen);
29
+
30
+ // Only show when the flow is empty and the full chat panel isn't open
31
+ const isFlowEmpty = nodes.length === 0;
32
+ const shouldShow = isFlowEmpty && !isChatOpen;
33
+
34
+ const handleSubmit = useCallback(() => {
35
+ const text = value.trim();
36
+ if (!text) {
37
+ return;
38
+ }
39
+
40
+ // Queue the prompt and open the panel — ChatPanel will consume it
41
+ useChatStore.getState().setPendingPrompt(text);
42
+ setValue('');
43
+ }, [value]);
44
+
45
+ const handleKeyDown = useCallback(
46
+ (e: React.KeyboardEvent) => {
47
+ if (e.key === 'Enter' && !e.shiftKey) {
48
+ e.preventDefault();
49
+ handleSubmit();
50
+ }
51
+ },
52
+ [handleSubmit],
53
+ );
54
+
55
+ const handleAddNode = useCallback(() => {
56
+ setNodeSidebarOpen(true);
57
+ }, [setNodeSidebarOpen]);
58
+
59
+ // Auto-focus the input after a short delay when visible
60
+ useEffect(() => {
61
+ if (shouldShow) {
62
+ const timer = setTimeout(() => inputRef.current?.focus(), 400);
63
+ return () => clearTimeout(timer);
64
+ }
65
+ }, [shouldShow]);
66
+
67
+ if (!shouldShow) {
68
+ return null;
69
+ }
70
+
71
+ return (
72
+ <div
73
+ className={cn(
74
+ 'absolute inset-0 z-20 flex items-center justify-center pointer-events-none',
75
+ 'animate-in fade-in duration-500',
76
+ className,
77
+ )}
78
+ >
79
+ <div className="flex items-center gap-4 pointer-events-auto">
80
+ {/* Add Node button */}
81
+ <button
82
+ type="button"
83
+ onClick={handleAddNode}
84
+ className={cn(
85
+ 'flex items-center gap-2 px-5 py-3 rounded-xl',
86
+ 'bg-primary text-primary-foreground',
87
+ 'text-sm font-medium',
88
+ 'shadow-md hover:shadow-lg hover:bg-primary/90',
89
+ 'transition-all duration-200',
90
+ 'cursor-pointer',
91
+ )}
92
+ >
93
+ <Plus className="size-4" />
94
+ Add Node
95
+ </button>
96
+
97
+ {/* "or" separator */}
98
+ <div className="flex items-center gap-3">
99
+ <span className="text-xs font-medium tracking-wide uppercase text-muted-foreground">
100
+ or
101
+ </span>
102
+ </div>
103
+
104
+ {/* Chat input */}
105
+ <div
106
+ className={cn(
107
+ 'flex items-end gap-2 w-[420px] rounded-xl px-3 py-2.5',
108
+ 'bg-background/95 backdrop-blur-sm',
109
+ 'border border-primary/40 ring-1 ring-primary/15',
110
+ 'shadow-md shadow-primary/5',
111
+ 'transition-all duration-200',
112
+ focused && 'shadow-lg shadow-primary/10 border-primary/60 ring-2 ring-primary/25',
113
+ )}
114
+ >
115
+ <textarea
116
+ ref={inputRef}
117
+ value={value}
118
+ onChange={(e) => setValue(e.target.value)}
119
+ onKeyDown={handleKeyDown}
120
+ onFocus={() => setFocused(true)}
121
+ onBlur={() => setFocused(false)}
122
+ placeholder="Describe what you need done…"
123
+ className={cn(
124
+ 'flex-1 resize-none bg-transparent text-sm leading-relaxed',
125
+ 'placeholder:text-muted-foreground/50',
126
+ 'focus:outline-none',
127
+ 'min-h-[72px] max-h-[120px] py-1.5 px-1',
128
+ )}
129
+ rows={3}
130
+ />
131
+ <button
132
+ type="button"
133
+ onClick={handleSubmit}
134
+ disabled={!value.trim()}
135
+ className={cn(
136
+ 'flex items-center justify-center shrink-0',
137
+ 'size-7 rounded-full',
138
+ 'transition-all duration-150',
139
+ value.trim()
140
+ ? 'bg-primary text-primary-foreground hover:bg-primary/90 cursor-pointer'
141
+ : 'bg-muted text-muted-foreground cursor-default',
142
+ )}
143
+ >
144
+ <ArrowUp className="size-4" />
145
+ </button>
146
+ </div>
147
+ </div>
148
+ </div>
149
+ );
150
+ }