@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,1980 @@
1
+ /**
2
+ * Example: Static demo data for showcasing Invect flows in documentation.
3
+ *
4
+ * This file demonstrates the shape of data needed to power the DemoInvect
5
+ * and FlowViewer components without a backend server.
6
+ */
7
+
8
+ import type { DemoData } from './demo-api-client';
9
+ import type { NodeDefinition } from '../types/node-definition.types';
10
+ import type { ReactFlowNodeData } from '@invect/core/types';
11
+ import type { Node, Edge } from '@xyflow/react';
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // 1. Node Definitions — describes available node types for the palette & config
15
+ // ---------------------------------------------------------------------------
16
+
17
+ export const sampleNodeDefinitions: NodeDefinition[] = [
18
+ {
19
+ type: 'core.input',
20
+ label: 'Flow Input',
21
+ description: 'Entry point for the flow. Defines input variables.',
22
+ icon: 'ArrowRightToLine',
23
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
24
+ input: undefined,
25
+ outputs: [{ id: 'output', label: 'Output', type: 'any' }],
26
+ paramFields: [{ name: 'inputSchema', label: 'Input Schema', type: 'json', required: false }],
27
+ maxInstances: 1,
28
+ },
29
+ {
30
+ type: 'core.output',
31
+ label: 'Flow Output',
32
+ description: 'Exit point for the flow. Returns data to the caller.',
33
+ icon: 'ArrowLeftFromLine',
34
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
35
+ input: { id: 'input', label: 'Input', type: 'any' },
36
+ outputs: [],
37
+ paramFields: [],
38
+ maxInstances: 1,
39
+ },
40
+ {
41
+ type: 'core.model',
42
+ label: 'AI Model',
43
+ description: 'Send a prompt to an LLM (OpenAI, Anthropic, etc.)',
44
+ icon: 'Brain',
45
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
46
+ input: { id: 'input', label: 'Input', type: 'any' },
47
+ outputs: [{ id: 'output', label: 'Output', type: 'string' }],
48
+ paramFields: [
49
+ {
50
+ name: 'credentialId',
51
+ label: 'API Credential',
52
+ type: 'credential',
53
+ required: true,
54
+ credentialTypes: ['llm'],
55
+ },
56
+ {
57
+ name: 'model',
58
+ label: 'Model',
59
+ type: 'select',
60
+ required: true,
61
+ options: [
62
+ { label: 'GPT-4o', value: 'gpt-4o' },
63
+ { label: 'GPT-4o Mini', value: 'gpt-4o-mini' },
64
+ { label: 'Claude Sonnet 4', value: 'claude-sonnet-4-20250514' },
65
+ ],
66
+ },
67
+ { name: 'prompt', label: 'Prompt', type: 'textarea', required: true },
68
+ { name: 'systemPrompt', label: 'System Prompt', type: 'textarea', required: false },
69
+ ],
70
+ },
71
+ {
72
+ type: 'core.jq',
73
+ label: 'JQ Transform',
74
+ description: 'Transform JSON data using JQ expressions.',
75
+ icon: 'Braces',
76
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
77
+ input: { id: 'input', label: 'Input', type: 'any' },
78
+ outputs: [{ id: 'output', label: 'Output', type: 'any' }],
79
+ paramFields: [{ name: 'query', label: 'JQ Query', type: 'code', required: true }],
80
+ },
81
+ {
82
+ type: 'core.if_else',
83
+ label: 'If/Else',
84
+ description: 'Conditional branching based on a JavaScript expression.',
85
+ icon: 'GitBranch',
86
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
87
+ input: { id: 'input', label: 'Input', type: 'any' },
88
+ outputs: [
89
+ { id: 'true_output', label: 'True', type: 'any' },
90
+ { id: 'false_output', label: 'False', type: 'any' },
91
+ ],
92
+ paramFields: [{ name: 'condition', label: 'Condition', type: 'code', required: true }],
93
+ },
94
+ {
95
+ type: 'http.request',
96
+ label: 'HTTP Request',
97
+ description: 'Make an HTTP request to any URL.',
98
+ icon: 'Globe',
99
+ provider: { id: 'http', name: 'HTTP', icon: 'Globe' },
100
+ input: { id: 'input', label: 'Input', type: 'any' },
101
+ outputs: [{ id: 'output', label: 'Response', type: 'object' }],
102
+ paramFields: [
103
+ {
104
+ name: 'method',
105
+ label: 'Method',
106
+ type: 'select',
107
+ required: true,
108
+ options: [
109
+ { label: 'GET', value: 'GET' },
110
+ { label: 'POST', value: 'POST' },
111
+ { label: 'PUT', value: 'PUT' },
112
+ { label: 'DELETE', value: 'DELETE' },
113
+ ],
114
+ defaultValue: 'GET',
115
+ },
116
+ { name: 'url', label: 'URL', type: 'text', required: true },
117
+ { name: 'headers', label: 'Headers', type: 'json', required: false },
118
+ { name: 'body', label: 'Body', type: 'json', required: false },
119
+ ],
120
+ },
121
+ {
122
+ type: 'gmail.send_message',
123
+ label: 'Send Email',
124
+ description: 'Send an email via Gmail.',
125
+ icon: 'Mail',
126
+ provider: { id: 'gmail', name: 'Gmail', icon: 'Mail' },
127
+ input: { id: 'input', label: 'Input', type: 'any' },
128
+ outputs: [{ id: 'output', label: 'Result', type: 'object' }],
129
+ paramFields: [
130
+ { name: 'to', label: 'To', type: 'text', required: true },
131
+ { name: 'subject', label: 'Subject', type: 'text', required: true },
132
+ { name: 'body', label: 'Body', type: 'textarea', required: true },
133
+ ],
134
+ },
135
+ {
136
+ type: 'gmail.get_message',
137
+ label: 'Get Email',
138
+ description: 'Retrieve a Gmail message by ID.',
139
+ icon: 'Mail',
140
+ provider: { id: 'gmail', name: 'Gmail', icon: 'Mail' },
141
+ input: { id: 'input', label: 'Input', type: 'any' },
142
+ outputs: [{ id: 'output', label: 'Message', type: 'object' }],
143
+ paramFields: [{ name: 'messageId', label: 'Message ID', type: 'text', required: true }],
144
+ },
145
+ {
146
+ type: 'gmail.modify_labels',
147
+ label: 'Modify Labels',
148
+ description: 'Add or remove labels from a Gmail message.',
149
+ icon: 'Mail',
150
+ provider: { id: 'gmail', name: 'Gmail', icon: 'Mail' },
151
+ input: { id: 'input', label: 'Input', type: 'any' },
152
+ outputs: [{ id: 'output', label: 'Result', type: 'object' }],
153
+ paramFields: [
154
+ { name: 'messageId', label: 'Message ID', type: 'text', required: true },
155
+ { name: 'addLabels', label: 'Add Labels', type: 'text', required: false },
156
+ { name: 'removeLabels', label: 'Remove Labels', type: 'text', required: false },
157
+ ],
158
+ },
159
+ {
160
+ type: 'slack.send_message',
161
+ label: 'Send Message',
162
+ description: 'Send a message to a Slack channel.',
163
+ icon: 'MessageSquare',
164
+ provider: { id: 'slack', name: 'Slack', icon: 'MessageSquare' },
165
+ input: { id: 'input', label: 'Input', type: 'any' },
166
+ outputs: [{ id: 'output', label: 'Result', type: 'object' }],
167
+ paramFields: [
168
+ { name: 'channel', label: 'Channel', type: 'text', required: true },
169
+ { name: 'text', label: 'Message', type: 'textarea', required: true },
170
+ ],
171
+ },
172
+ {
173
+ type: 'linear.create_issue',
174
+ label: 'Create Issue',
175
+ description: 'Create a new issue in Linear.',
176
+ icon: 'SquarePen',
177
+ provider: { id: 'linear', name: 'Linear', icon: 'SquarePen' },
178
+ input: { id: 'input', label: 'Input', type: 'any' },
179
+ outputs: [{ id: 'output', label: 'Issue', type: 'object' }],
180
+ paramFields: [
181
+ { name: 'title', label: 'Title', type: 'text', required: true },
182
+ { name: 'description', label: 'Description', type: 'textarea', required: false },
183
+ { name: 'teamId', label: 'Team ID', type: 'text', required: true },
184
+ ],
185
+ },
186
+ {
187
+ type: 'linear.update_issue',
188
+ label: 'Update Issue',
189
+ description: 'Update an existing issue in Linear.',
190
+ icon: 'SquarePen',
191
+ provider: { id: 'linear', name: 'Linear', icon: 'SquarePen' },
192
+ input: { id: 'input', label: 'Input', type: 'any' },
193
+ outputs: [{ id: 'output', label: 'Issue', type: 'object' }],
194
+ paramFields: [
195
+ { name: 'issueId', label: 'Issue ID', type: 'text', required: true },
196
+ { name: 'stateId', label: 'State', type: 'text', required: false },
197
+ { name: 'comment', label: 'Comment', type: 'textarea', required: false },
198
+ ],
199
+ },
200
+ {
201
+ type: 'github.create_issue',
202
+ label: 'Create Issue',
203
+ description: 'Create a new GitHub issue.',
204
+ icon: 'Github',
205
+ provider: { id: 'github', name: 'GitHub', icon: 'Github' },
206
+ input: { id: 'input', label: 'Input', type: 'any' },
207
+ outputs: [{ id: 'output', label: 'Issue', type: 'object' }],
208
+ paramFields: [
209
+ { name: 'owner', label: 'Owner', type: 'text', required: true },
210
+ { name: 'repo', label: 'Repository', type: 'text', required: true },
211
+ { name: 'title', label: 'Title', type: 'text', required: true },
212
+ { name: 'body', label: 'Body', type: 'textarea', required: false },
213
+ ],
214
+ },
215
+ {
216
+ type: 'trigger.webhook',
217
+ label: 'Webhook Trigger',
218
+ description: 'Trigger a flow from an incoming webhook.',
219
+ icon: 'Webhook',
220
+ provider: { id: 'triggers', name: 'Triggers', icon: 'Zap' },
221
+ input: undefined,
222
+ outputs: [{ id: 'output', label: 'Payload', type: 'any' }],
223
+ paramFields: [],
224
+ maxInstances: 1,
225
+ },
226
+ {
227
+ type: 'AGENT',
228
+ label: 'AI Agent',
229
+ description: 'Autonomous AI agent with iterative tool-calling loop.',
230
+ icon: 'Bot',
231
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
232
+ input: { id: 'input', label: 'Input', type: 'any' },
233
+ outputs: [{ id: 'output', label: 'Output', type: 'any' }],
234
+ paramFields: [
235
+ {
236
+ name: 'credentialId',
237
+ label: 'API Credential',
238
+ type: 'credential',
239
+ required: true,
240
+ credentialTypes: ['llm'],
241
+ },
242
+ {
243
+ name: 'model',
244
+ label: 'Model',
245
+ type: 'select',
246
+ required: true,
247
+ options: [
248
+ { label: 'GPT-4o', value: 'gpt-4o' },
249
+ { label: 'Claude Sonnet 4', value: 'claude-sonnet-4-20250514' },
250
+ ],
251
+ },
252
+ { name: 'taskPrompt', label: 'Task Prompt', type: 'textarea', required: true },
253
+ { name: 'systemPrompt', label: 'System Prompt', type: 'textarea', required: false },
254
+ ],
255
+ },
256
+ {
257
+ type: 'core.switch',
258
+ label: 'Switch',
259
+ description: 'Multi-way conditional branching based on JS expressions.',
260
+ icon: 'GitFork',
261
+ provider: { id: 'core', name: 'Core', icon: 'Blocks' },
262
+ input: { id: 'input', label: 'Input', type: 'any' },
263
+ dynamicOutputs: true,
264
+ outputs: [
265
+ { id: 'case_0', label: 'Case 0', type: 'any' },
266
+ { id: 'default', label: 'Default', type: 'any' },
267
+ ],
268
+ paramFields: [
269
+ {
270
+ name: 'matchMode',
271
+ label: 'Match Mode',
272
+ type: 'select',
273
+ required: false,
274
+ options: [
275
+ { label: 'First match', value: 'first' },
276
+ { label: 'All matches', value: 'all' },
277
+ ],
278
+ },
279
+ { name: 'cases', label: 'Cases', type: 'switch-cases', required: true },
280
+ ],
281
+ },
282
+ {
283
+ type: 'github.create_pull_request',
284
+ label: 'Create Pull Request',
285
+ description: 'Create a new pull request on GitHub.',
286
+ icon: 'GitPullRequest',
287
+ provider: { id: 'github', name: 'GitHub', icon: 'Github' },
288
+ input: { id: 'input', label: 'Input', type: 'any' },
289
+ outputs: [{ id: 'output', label: 'PR', type: 'object' }],
290
+ paramFields: [
291
+ { name: 'owner', label: 'Owner', type: 'text', required: true },
292
+ { name: 'repo', label: 'Repository', type: 'text', required: true },
293
+ { name: 'title', label: 'Title', type: 'text', required: true },
294
+ { name: 'body', label: 'Body', type: 'textarea', required: false },
295
+ { name: 'head', label: 'Head Branch', type: 'text', required: true },
296
+ { name: 'base', label: 'Base Branch', type: 'text', required: true },
297
+ ],
298
+ },
299
+ ];
300
+
301
+ // ---------------------------------------------------------------------------
302
+ // 2. Example Flow: Input → AI Model → JQ Transform → Output
303
+ // ---------------------------------------------------------------------------
304
+
305
+ export const simpleFlowNodes: Node<ReactFlowNodeData>[] = [
306
+ {
307
+ id: 'node-input',
308
+ type: 'core.input',
309
+ position: { x: 0, y: 100 },
310
+ data: {
311
+ id: 'node-input',
312
+ type: 'core.input',
313
+ display_name: 'User Query',
314
+ reference_id: 'user_query',
315
+ status: 'idle',
316
+ params: {},
317
+ },
318
+ },
319
+ {
320
+ id: 'node-model',
321
+ type: 'core.model',
322
+ position: { x: 300, y: 100 },
323
+ data: {
324
+ id: 'node-model',
325
+ type: 'core.model',
326
+ display_name: 'Summarize',
327
+ reference_id: 'summarize',
328
+ status: 'idle',
329
+ params: {
330
+ model: 'gpt-4o',
331
+ prompt: 'Summarize the following text:\n\n{{ user_query }}',
332
+ systemPrompt: 'You are a helpful assistant that summarizes text concisely.',
333
+ },
334
+ },
335
+ },
336
+ {
337
+ id: 'node-jq',
338
+ type: 'core.jq',
339
+ position: { x: 600, y: 100 },
340
+ data: {
341
+ id: 'node-jq',
342
+ type: 'core.jq',
343
+ display_name: 'Format Output',
344
+ reference_id: 'format_output',
345
+ status: 'idle',
346
+ params: {
347
+ query: '{ summary: .summarize, timestamp: now | todate }',
348
+ },
349
+ },
350
+ },
351
+ {
352
+ id: 'node-output',
353
+ type: 'core.output',
354
+ position: { x: 900, y: 100 },
355
+ data: {
356
+ id: 'node-output',
357
+ type: 'core.output',
358
+ display_name: 'Result',
359
+ reference_id: 'result',
360
+ status: 'idle',
361
+ params: {},
362
+ },
363
+ },
364
+ ];
365
+
366
+ export const simpleFlowEdges: Edge[] = [
367
+ { id: 'e-input-model', source: 'node-input', target: 'node-model' },
368
+ { id: 'e-model-jq', source: 'node-model', target: 'node-jq' },
369
+ { id: 'e-jq-output', source: 'node-jq', target: 'node-output' },
370
+ ];
371
+
372
+ // ---------------------------------------------------------------------------
373
+ // 3. Example Flow with Branching: Input → If/Else → (HTTP | Email) → Output
374
+ // ---------------------------------------------------------------------------
375
+
376
+ export const branchingFlowNodes: Node<ReactFlowNodeData>[] = [
377
+ {
378
+ id: 'b-input',
379
+ type: 'core.input',
380
+ position: { x: 0, y: 150 },
381
+ data: {
382
+ id: 'b-input',
383
+ type: 'core.input',
384
+ display_name: 'Webhook Data',
385
+ reference_id: 'webhook_data',
386
+ status: 'idle',
387
+ params: {},
388
+ },
389
+ },
390
+ {
391
+ id: 'b-branch',
392
+ type: 'core.if_else',
393
+ position: { x: 300, y: 150 },
394
+ data: {
395
+ id: 'b-branch',
396
+ type: 'core.if_else',
397
+ display_name: 'Is Priority?',
398
+ reference_id: 'is_priority',
399
+ status: 'idle',
400
+ params: {
401
+ condition: '{{ webhook_data.priority === "high" }}',
402
+ },
403
+ },
404
+ },
405
+ {
406
+ id: 'b-http',
407
+ type: 'http.request',
408
+ position: { x: 600, y: 50 },
409
+ data: {
410
+ id: 'b-http',
411
+ type: 'http.request',
412
+ display_name: 'Create Ticket',
413
+ reference_id: 'create_ticket',
414
+ status: 'idle',
415
+ params: {
416
+ method: 'POST',
417
+ url: 'https://api.example.com/tickets',
418
+ body: '{{ { title: is_priority.subject, priority: "urgent" } }}',
419
+ },
420
+ },
421
+ },
422
+ {
423
+ id: 'b-email',
424
+ type: 'gmail.send_message',
425
+ position: { x: 600, y: 280 },
426
+ data: {
427
+ id: 'b-email',
428
+ type: 'gmail.send_message',
429
+ display_name: 'Notify Team',
430
+ reference_id: 'notify_team',
431
+ status: 'idle',
432
+ params: {
433
+ to: 'team@example.com',
434
+ subject: 'Low priority notification',
435
+ body: '{{ is_priority.message }}',
436
+ },
437
+ },
438
+ },
439
+ {
440
+ id: 'b-output',
441
+ type: 'core.output',
442
+ position: { x: 900, y: 150 },
443
+ data: {
444
+ id: 'b-output',
445
+ type: 'core.output',
446
+ display_name: 'Done',
447
+ reference_id: 'done',
448
+ status: 'idle',
449
+ params: {},
450
+ },
451
+ },
452
+ ];
453
+
454
+ export const branchingFlowEdges: Edge[] = [
455
+ { id: 'be-input-branch', source: 'b-input', target: 'b-branch' },
456
+ { id: 'be-branch-http', source: 'b-branch', target: 'b-http', sourceHandle: 'true_output' },
457
+ { id: 'be-branch-email', source: 'b-branch', target: 'b-email', sourceHandle: 'false_output' },
458
+ { id: 'be-http-output', source: 'b-http', target: 'b-output' },
459
+ { id: 'be-email-output', source: 'b-email', target: 'b-output' },
460
+ ];
461
+
462
+ // ---------------------------------------------------------------------------
463
+ // 3b. Showcase Flow: Linear Ticket Triage → Agent Investigation → Switch → Handlers
464
+ // ---------------------------------------------------------------------------
465
+
466
+ /** A realistic webhook payload from Linear */
467
+ const linearWebhookPayload = {
468
+ action: 'create',
469
+ type: 'Issue',
470
+ data: {
471
+ id: 'LIN-4821',
472
+ identifier: 'ENG-4821',
473
+ title: 'Payment processing fails with 502 for Stripe webhook handler',
474
+ description:
475
+ 'Multiple customers reporting failed payments since 14:30 UTC. Stripe webhook endpoint returns 502. Logs show connection pool exhaustion in payment-service.',
476
+ priority: 1,
477
+ state: { name: 'Triage' },
478
+ team: { key: 'ENG', name: 'Engineering' },
479
+ creator: { name: 'Sarah Chen', email: 'sarah@acme.com' },
480
+ labels: [{ name: 'bug' }, { name: 'payments' }, { name: 'urgent' }],
481
+ url: 'https://linear.app/acme/issue/ENG-4821',
482
+ createdAt: '2025-04-07T14:32:00Z',
483
+ },
484
+ };
485
+
486
+ /** Agent investigation result — what the agent concluded */
487
+ const investigationResult = {
488
+ summary:
489
+ 'Payment processing failures caused by PostgreSQL connection pool exhaustion in payment-service. The Stripe webhook handler opens a new DB connection per request but the pool limit (20) was exceeded during a traffic spike at 14:30 UTC. 847 failed payments in the last 2 hours affecting ~320 customers.',
490
+ root_cause:
491
+ 'Connection pool exhaustion in payment-service. The `handleStripeWebhook()` function in `src/services/payments/stripe-handler.ts` acquires a connection but does not release it on the error path (missing `finally` block). Under normal load this is masked by the pool recycler, but the 3x traffic spike from the flash sale exhausted all 20 connections.',
492
+ severity: 'critical',
493
+ issue_type: 'bug',
494
+ recommended_action:
495
+ 'Hotfix: Add `finally { connection.release() }` in stripe-handler.ts. Increase pool size to 50 as interim measure. Consider switching to a connection-per-transaction pattern.',
496
+ affected_customers: 320,
497
+ failed_transactions: 847,
498
+ estimated_revenue_impact: '$42,350',
499
+ };
500
+
501
+ /** GitHub PR creation result */
502
+ const prResult = {
503
+ id: 98712,
504
+ number: 4293,
505
+ html_url: 'https://github.com/acme/platform/pull/4293',
506
+ title: 'fix: Payment processing fails with 502 for Stripe webhook handler',
507
+ state: 'open',
508
+ head: { ref: 'fix/ENG-4821' },
509
+ base: { ref: 'main' },
510
+ created_at: '2025-04-07T16:32:45Z',
511
+ };
512
+
513
+ /** Agent tool definitions for the showcase flow's Investigate Ticket agent node */
514
+ export const showcaseAgentTools: Array<{
515
+ id: string;
516
+ name: string;
517
+ description: string;
518
+ category: string;
519
+ provider?: { id: string; name: string; icon: string };
520
+ }> = [
521
+ {
522
+ id: 'postgres.execute_query',
523
+ name: 'Query Database',
524
+ description: 'Execute a SQL query against a PostgreSQL database.',
525
+ category: 'data',
526
+ provider: { id: 'postgres', name: 'PostgreSQL', icon: 'Database' },
527
+ },
528
+ {
529
+ id: 'sentry.list_issues',
530
+ name: 'Sentry Issues',
531
+ description: 'Search Sentry for recent errors matching the ticket.',
532
+ category: 'web',
533
+ provider: { id: 'sentry', name: 'Sentry', icon: 'Bug' },
534
+ },
535
+ {
536
+ id: 'cloudwatch.start_query',
537
+ name: 'AWS Log Insights',
538
+ description: 'Query CloudWatch Logs Insights for anomalies.',
539
+ category: 'data',
540
+ provider: { id: 'cloudwatch', name: 'CloudWatch', icon: 'Cloud' },
541
+ },
542
+ {
543
+ id: 'notion.search',
544
+ name: 'Search Notion',
545
+ description: 'Search Notion workspace for relevant documentation.',
546
+ category: 'web',
547
+ provider: { id: 'notion', name: 'Notion', icon: 'FileText' },
548
+ },
549
+ {
550
+ id: 'github.get_file_content',
551
+ name: 'Read Source File',
552
+ description: 'Read a file from the GitHub repository.',
553
+ category: 'code',
554
+ provider: { id: 'github', name: 'GitHub', icon: 'Github' },
555
+ },
556
+ ];
557
+
558
+ export const showcaseFlowNodes: Node<ReactFlowNodeData>[] = [
559
+ // --- Row 1: Trigger + Agent investigation ---
560
+ {
561
+ id: 's-webhook',
562
+ type: 'trigger.webhook',
563
+ position: { x: 0, y: 240 },
564
+ data: {
565
+ id: 's-webhook',
566
+ type: 'trigger.webhook',
567
+ display_name: 'Linear Webhook',
568
+ reference_id: 'linear_webhook',
569
+ status: 'idle',
570
+ params: {
571
+ credentialId: 'linear-test',
572
+ },
573
+ },
574
+ },
575
+ {
576
+ id: 's-agent',
577
+ type: 'AGENT',
578
+ position: { x: 280, y: 240 },
579
+ data: {
580
+ id: 's-agent',
581
+ type: 'AGENT',
582
+ display_name: 'Investigation Agent',
583
+ reference_id: 'investigation_agent',
584
+ status: 'idle',
585
+ params: {
586
+ credentialId: 'openai-test',
587
+ model: 'gpt-4o',
588
+ taskPrompt:
589
+ 'Investigate Linear ticket "{{ linear_webhook.title }}".\n\n1. Query the database for related records\n2. Search Sentry for recent errors\n3. Check AWS logs for anomalies\n4. Search Notion for relevant docs\n5. Read related source files on GitHub\n\nOutput a JSON object with: summary, root_cause, severity (critical/high/medium/low), issue_type (bug/feature_request/incident), and recommended_action.',
590
+ systemPrompt:
591
+ 'You are a senior on-call engineer performing ticket triage. Be thorough but concise.',
592
+ maxIterations: 10,
593
+ stopCondition: 'explicit_stop',
594
+ temperature: 0.7,
595
+ toolTimeoutMs: 30000,
596
+ maxConversationTokens: 100000,
597
+ enableParallelTools: true,
598
+ useBatchProcessing: false,
599
+ maxTokens: 2000,
600
+ addedTools: [
601
+ {
602
+ instanceId: 'tool_qn4q8nv0',
603
+ toolId: 'postgres.execute_query',
604
+ name: 'Query Database',
605
+ description: 'Query PostgreSQL for related records',
606
+ params: { _aiChosenModes: { query: true } },
607
+ },
608
+ {
609
+ instanceId: 'tool_qvs9k37e',
610
+ toolId: 'sentry.list_issues',
611
+ name: 'Sentry Issues',
612
+ description: 'Search Sentry for recent errors matching the ticket',
613
+ params: { _aiChosenModes: { query: true } },
614
+ },
615
+ {
616
+ instanceId: 'tool_bwhiecqs',
617
+ toolId: 'cloudwatch.start_query',
618
+ name: 'AWS Log Insights',
619
+ description: 'Query CloudWatch Logs Insights for anomalies',
620
+ params: { _aiChosenModes: { logGroupName: true, queryString: true } },
621
+ },
622
+ {
623
+ instanceId: 'tool_cxbfi7au',
624
+ toolId: 'notion.search',
625
+ name: 'Search Notion',
626
+ description: 'Search Notion workspace for relevant documentation',
627
+ params: { _aiChosenModes: { query: true } },
628
+ },
629
+ {
630
+ instanceId: 'tool_dez9g3z0',
631
+ toolId: 'github.get_file_content',
632
+ name: 'Read Source File',
633
+ description: 'Read a file from the GitHub repository',
634
+ params: { _aiChosenModes: { owner: true, repo: true, path: true } },
635
+ },
636
+ ],
637
+ },
638
+ },
639
+ },
640
+
641
+ // --- Row 2: Switch on issue type ---
642
+ {
643
+ id: 's-switch',
644
+ type: 'core.switch',
645
+ position: { x: 580, y: 220 },
646
+ data: {
647
+ id: 's-switch',
648
+ type: 'core.switch',
649
+ display_name: 'Route by Issue Type',
650
+ reference_id: 'route_by_issue_type',
651
+ status: 'idle',
652
+ params: {
653
+ matchMode: 'first',
654
+ cases: [
655
+ { slug: 'bug', label: 'Bug', expression: 'investigation.issue_type === "bug"' },
656
+ {
657
+ slug: 'feature',
658
+ label: 'Feature Request',
659
+ expression: 'investigation.issue_type === "feature_request"',
660
+ },
661
+ {
662
+ slug: 'incident',
663
+ label: 'Incident',
664
+ expression: 'investigation.issue_type === "incident"',
665
+ },
666
+ ],
667
+ },
668
+ },
669
+ },
670
+
671
+ // --- Row 3: Handler for each branch ---
672
+
673
+ // Bug path → Create PR with fix
674
+ {
675
+ id: 's-gh-pr',
676
+ type: 'github.create_pull_request',
677
+ position: { x: 900, y: 80 },
678
+ data: {
679
+ id: 's-gh-pr',
680
+ type: 'github.create_pull_request',
681
+ display_name: 'Create Fix PR',
682
+ reference_id: 'create_fix_pr',
683
+ status: 'idle',
684
+ params: {
685
+ credentialId: 'github-test',
686
+ owner: 'acme',
687
+ repo: 'platform',
688
+ title: 'fix: {{ linear_webhook.title }}',
689
+ body: '{{ investigation.summary }}\n\nRoot cause: {{ investigation.root_cause }}',
690
+ head: 'fix/{{ linear_webhook.identifier }}',
691
+ base: 'main',
692
+ },
693
+ },
694
+ },
695
+
696
+ // Feature request path → Notify product channel
697
+ {
698
+ id: 's-slack-feature',
699
+ type: 'slack.send_message',
700
+ position: { x: 900, y: 190 },
701
+ data: {
702
+ id: 's-slack-feature',
703
+ type: 'slack.send_message',
704
+ display_name: 'Notify #product',
705
+ reference_id: 'notify_product',
706
+ status: 'idle',
707
+ params: {
708
+ credentialId: 'slack-test',
709
+ channel: '#product-requests',
710
+ text: '*New feature request:* {{ linear_webhook.title }}\n\n{{ investigation.summary }}',
711
+ },
712
+ },
713
+ },
714
+
715
+ // Incident path → PagerDuty escalation
716
+ {
717
+ id: 's-pagerduty',
718
+ type: 'http.request',
719
+ position: { x: 900, y: 290 },
720
+ data: {
721
+ id: 's-pagerduty',
722
+ type: 'http.request',
723
+ display_name: 'PagerDuty Alert',
724
+ reference_id: 'pagerduty_alert',
725
+ status: 'idle',
726
+ params: {
727
+ method: 'POST',
728
+ url: 'https://events.pagerduty.com/v2/enqueue',
729
+ body: '{"routing_key": "R0123456789abcdef", "event_action": "trigger", "payload": {"summary": "{{ investigation.summary }}", "severity": "{{ investigation.severity }}", "source": "invect-triage"}}',
730
+ },
731
+ },
732
+ },
733
+
734
+ // Default path → Notify Slack
735
+ {
736
+ id: 's-slack-default',
737
+ type: 'slack.send_message',
738
+ position: { x: 900, y: 390 },
739
+ data: {
740
+ id: 's-slack-default',
741
+ type: 'slack.send_message',
742
+ display_name: 'Notify #triage',
743
+ reference_id: 'notify_triage',
744
+ status: 'idle',
745
+ params: {
746
+ credentialId: 'slack-test',
747
+ channel: '#triage',
748
+ text: '*Unclassified ticket:* {{ linear_webhook.title }}\nSeverity: {{ investigation.severity }}\n\n{{ investigation.summary }}',
749
+ },
750
+ },
751
+ },
752
+
753
+ // --- Row 4: Merge — all branches converge here ---
754
+ // Demonstrates multi-source-aware skip propagation: this node executes
755
+ // because the bug branch (Create Fix PR) is live, even though the other
756
+ // three source edges come from skipped nodes.
757
+ {
758
+ id: 's-linear-update',
759
+ type: 'linear.update_issue',
760
+ position: { x: 1300, y: 240 },
761
+ data: {
762
+ id: 's-linear-update',
763
+ type: 'linear.update_issue',
764
+ display_name: 'Update Linear Ticket',
765
+ reference_id: 'update_linear_ticket',
766
+ status: 'idle',
767
+ params: {
768
+ credentialId: 'linear-test',
769
+ issueId: '{{ linear_webhook.identifier }}',
770
+ stateId: 'in-progress',
771
+ comment:
772
+ 'Automated triage complete.\n\n**Severity:** {{ investigation.severity }}\n**Root cause:** {{ investigation.root_cause }}\n\n{% if fix_pr.html_url %}Fix PR: {{ fix_pr.html_url }}{% else %}No PR created — see action above.{% endif %}',
773
+ },
774
+ },
775
+ },
776
+ ];
777
+
778
+ export const showcaseFlowEdges: Edge[] = [
779
+ { id: 'se-webhook-agent', source: 's-webhook', target: 's-agent' },
780
+ { id: 'se-agent-switch', source: 's-agent', target: 's-switch' },
781
+ { id: 'se-switch-pr', source: 's-switch', target: 's-gh-pr', sourceHandle: 'bug' },
782
+ {
783
+ id: 'se-switch-feature',
784
+ source: 's-switch',
785
+ target: 's-slack-feature',
786
+ sourceHandle: 'feature',
787
+ },
788
+ { id: 'se-switch-incident', source: 's-switch', target: 's-pagerduty', sourceHandle: 'incident' },
789
+ {
790
+ id: 'se-switch-triage-output',
791
+ source: 's-switch',
792
+ target: 's-slack-default',
793
+ sourceHandle: 'output',
794
+ },
795
+ {
796
+ id: 'se-switch-triage-default',
797
+ source: 's-switch',
798
+ target: 's-slack-default',
799
+ sourceHandle: 'default',
800
+ },
801
+ // All branches converge into Update Linear Ticket (diamond pattern)
802
+ { id: 'se-pr-linear', source: 's-gh-pr', target: 's-linear-update' },
803
+ { id: 'se-feature-linear', source: 's-slack-feature', target: 's-linear-update' },
804
+ { id: 'se-incident-linear', source: 's-pagerduty', target: 's-linear-update' },
805
+ { id: 'se-default-linear', source: 's-slack-default', target: 's-linear-update' },
806
+ ];
807
+
808
+ // ---------------------------------------------------------------------------
809
+ // 4. Dummy flow run + node executions for the triage flow
810
+ // ---------------------------------------------------------------------------
811
+
812
+ /** Tool call records from the agent investigation */
813
+ const agentToolResults = [
814
+ {
815
+ toolId: 'postgres.execute_query',
816
+ toolName: 'Query Database',
817
+ input: {
818
+ query:
819
+ "SELECT COUNT(*) as failed_count, COUNT(DISTINCT customer_id) as affected_customers FROM payments WHERE status = 'failed' AND created_at > NOW() - INTERVAL '2 hours'",
820
+ },
821
+ output: { rows: [{ failed_count: 847, affected_customers: 320 }], rowCount: 1 },
822
+ error: undefined,
823
+ success: true,
824
+ iteration: 1,
825
+ executionTimeMs: 120,
826
+ },
827
+ {
828
+ toolId: 'sentry.list_issues',
829
+ toolName: 'Sentry Issues',
830
+ input: { query: 'payment stripe webhook 502', project: 'payment-service' },
831
+ output: {
832
+ issues: [
833
+ {
834
+ id: 'SENTRY-89421',
835
+ title: 'ConnectionPool exhausted: cannot acquire connection',
836
+ count: 847,
837
+ firstSeen: '2025-04-07T14:31:00Z',
838
+ lastSeen: '2025-04-07T16:28:00Z',
839
+ level: 'error',
840
+ culprit: 'stripe-handler.ts in handleStripeWebhook',
841
+ },
842
+ ],
843
+ },
844
+ error: undefined,
845
+ success: true,
846
+ iteration: 2,
847
+ executionTimeMs: 340,
848
+ },
849
+ {
850
+ toolId: 'cloudwatch.start_query',
851
+ toolName: 'AWS Log Insights',
852
+ input: {
853
+ logGroup: '/ecs/payment-service',
854
+ query:
855
+ 'fields @timestamp, @message | filter @message like /connection pool|exhausted|502/ | sort @timestamp desc | limit 20',
856
+ startTime: '2025-04-07T14:00:00Z',
857
+ endTime: '2025-04-07T16:30:00Z',
858
+ },
859
+ output: {
860
+ results: [
861
+ {
862
+ timestamp: '2025-04-07T14:31:12Z',
863
+ message:
864
+ 'ERROR ConnectionPool: Cannot acquire connection — pool exhausted (20/20 active)',
865
+ },
866
+ {
867
+ timestamp: '2025-04-07T14:31:13Z',
868
+ message: 'ERROR StripeWebhookHandler: Failed to process payment_intent.succeeded — 502',
869
+ },
870
+ {
871
+ timestamp: '2025-04-07T14:30:58Z',
872
+ message: 'WARN ConnectionPool: Pool utilization at 95% (19/20) — approaching limit',
873
+ },
874
+ ],
875
+ totalResults: 1247,
876
+ },
877
+ error: undefined,
878
+ success: true,
879
+ iteration: 3,
880
+ executionTimeMs: 890,
881
+ },
882
+ {
883
+ toolId: 'notion.search',
884
+ toolName: 'Search Notion',
885
+ input: { query: 'payment service connection pool architecture' },
886
+ output: {
887
+ results: [
888
+ {
889
+ id: 'page-1',
890
+ title: 'Payment Service — Architecture & Runbook',
891
+ url: 'https://notion.so/acme/payment-service-arch',
892
+ snippet:
893
+ '...connection pool is configured to max 20 connections via PG_POOL_MAX env var. The pool recycler runs every 30s...',
894
+ },
895
+ {
896
+ id: 'page-2',
897
+ title: 'Incident Response: Database Connection Issues',
898
+ url: 'https://notion.so/acme/incident-db-connections',
899
+ snippet:
900
+ '...if pool exhaustion occurs, increase PG_POOL_MAX and restart. Long-term: implement connection-per-transaction...',
901
+ },
902
+ ],
903
+ },
904
+ error: undefined,
905
+ success: true,
906
+ iteration: 4,
907
+ executionTimeMs: 210,
908
+ },
909
+ {
910
+ toolId: 'github.get_file_content',
911
+ toolName: 'Read Source File',
912
+ input: { owner: 'acme', repo: 'platform', path: 'src/services/payments/stripe-handler.ts' },
913
+ output: {
914
+ content:
915
+ 'export async function handleStripeWebhook(event: StripeEvent) {\n const connection = await pool.acquire();\n try {\n const payment = await connection.query(...);\n await processPayment(payment);\n } catch (err) {\n logger.error("Webhook failed", err);\n throw err;\n // BUG: connection not released on error path!\n }\n}',
916
+ sha: 'abc123',
917
+ size: 2847,
918
+ path: 'src/services/payments/stripe-handler.ts',
919
+ },
920
+ error: undefined,
921
+ success: true,
922
+ iteration: 5,
923
+ executionTimeMs: 155,
924
+ },
925
+ ];
926
+
927
+ /** The switch node's evaluation — bug path matched */
928
+ const switchOutput = {
929
+ matchedCase: 'bug',
930
+ matchedLabel: 'Bug',
931
+ matchMode: 'first',
932
+ caseResults: [
933
+ { slug: 'bug', label: 'Bug', matched: true },
934
+ { slug: 'feature', label: 'Feature Request', matched: false },
935
+ { slug: 'incident', label: 'Incident', matched: false },
936
+ ],
937
+ };
938
+
939
+ // --- Flow run timestamps (realistic ~18s total execution) ---
940
+ const RUN_START = '2025-04-07T16:32:10.000Z';
941
+ const WEBHOOK_END = '2025-04-07T16:32:10.045Z';
942
+ const AGENT_START = '2025-04-07T16:32:10.050Z';
943
+ const AGENT_END = '2025-04-07T16:32:26.120Z';
944
+ const SWITCH_START = '2025-04-07T16:32:26.125Z';
945
+ const SWITCH_END = '2025-04-07T16:32:26.180Z';
946
+ const PR_START = '2025-04-07T16:32:26.185Z';
947
+ const PR_END = '2025-04-07T16:32:28.340Z';
948
+ const LINEAR_UPDATE_START = '2025-04-07T16:32:28.345Z';
949
+ const LINEAR_UPDATE_END = '2025-04-07T16:32:29.110Z';
950
+ const RUN_END = '2025-04-07T16:32:29.115Z';
951
+
952
+ export const showcaseFlowRun = {
953
+ id: 'run-triage-1',
954
+ flowId: 'flow-triage',
955
+ flowVersion: 1,
956
+ status: 'SUCCESS',
957
+ inputs: linearWebhookPayload,
958
+ outputs: {
959
+ create_fix_pr: prResult,
960
+ update_linear_ticket: {
961
+ id: 'LIN-4821',
962
+ identifier: 'ENG-4821',
963
+ state: { name: 'In Progress' },
964
+ },
965
+ },
966
+ error: undefined,
967
+ startedAt: RUN_START,
968
+ completedAt: RUN_END,
969
+ duration: 19115,
970
+ triggerType: 'webhook',
971
+ triggerNodeId: 's-webhook',
972
+ triggerData: { source: 'linear', event: 'Issue.create' },
973
+ };
974
+
975
+ export const showcaseNodeExecutions = [
976
+ // 1. Webhook trigger
977
+ {
978
+ id: 'nexec-webhook',
979
+ flowRunId: 'run-triage-1',
980
+ nodeId: 's-webhook',
981
+ nodeType: 'trigger.webhook',
982
+ status: 'SUCCESS',
983
+ inputs: {},
984
+ outputs: {
985
+ nodeType: 'trigger.webhook',
986
+ data: {
987
+ variables: {
988
+ output: { value: linearWebhookPayload.data, type: 'object' as const },
989
+ },
990
+ },
991
+ },
992
+ startedAt: RUN_START,
993
+ completedAt: WEBHOOK_END,
994
+ duration: 45,
995
+ retryCount: 0,
996
+ },
997
+ // 2. Agent investigation
998
+ {
999
+ id: 'nexec-agent',
1000
+ flowRunId: 'run-triage-1',
1001
+ nodeId: 's-agent',
1002
+ nodeType: 'AGENT',
1003
+ status: 'SUCCESS',
1004
+ inputs: {
1005
+ linear_webhook: linearWebhookPayload.data,
1006
+ },
1007
+ outputs: {
1008
+ nodeType: 'AGENT',
1009
+ data: {
1010
+ variables: {
1011
+ output: {
1012
+ value: {
1013
+ finalResponse: JSON.stringify(investigationResult, null, 2),
1014
+ toolResults: agentToolResults,
1015
+ iterations: 6,
1016
+ finishReason: 'completed',
1017
+ },
1018
+ type: 'object' as const,
1019
+ },
1020
+ },
1021
+ metadata: {
1022
+ model: 'gpt-4o',
1023
+ provider: 'openai',
1024
+ totalToolCalls: 5,
1025
+ iterations: 6,
1026
+ },
1027
+ },
1028
+ },
1029
+ startedAt: AGENT_START,
1030
+ completedAt: AGENT_END,
1031
+ duration: 16070,
1032
+ retryCount: 0,
1033
+ },
1034
+ // 3. Switch — routes to "bug" branch
1035
+ {
1036
+ id: 'nexec-switch',
1037
+ flowRunId: 'run-triage-1',
1038
+ nodeId: 's-switch',
1039
+ nodeType: 'core.switch',
1040
+ status: 'SUCCESS',
1041
+ inputs: {
1042
+ investigation_agent: investigationResult,
1043
+ },
1044
+ outputs: {
1045
+ nodeType: 'core.switch',
1046
+ data: {
1047
+ variables: {
1048
+ bug: { value: investigationResult, type: 'object' as const },
1049
+ },
1050
+ metadata: switchOutput,
1051
+ },
1052
+ },
1053
+ startedAt: SWITCH_START,
1054
+ completedAt: SWITCH_END,
1055
+ duration: 55,
1056
+ retryCount: 0,
1057
+ },
1058
+ // 4. Bug → Create PR (active path)
1059
+ {
1060
+ id: 'nexec-gh-pr',
1061
+ flowRunId: 'run-triage-1',
1062
+ nodeId: 's-gh-pr',
1063
+ nodeType: 'github.create_pull_request',
1064
+ status: 'SUCCESS',
1065
+ inputs: {
1066
+ route_by_issue_type: investigationResult,
1067
+ },
1068
+ outputs: {
1069
+ nodeType: 'github.create_pull_request',
1070
+ data: {
1071
+ variables: {
1072
+ output: { value: prResult, type: 'object' as const },
1073
+ },
1074
+ },
1075
+ },
1076
+ startedAt: PR_START,
1077
+ completedAt: PR_END,
1078
+ duration: 2155,
1079
+ retryCount: 0,
1080
+ },
1081
+ // 5. Feature path — skipped (switch didn't match)
1082
+ {
1083
+ id: 'nexec-slack-feature',
1084
+ flowRunId: 'run-triage-1',
1085
+ nodeId: 's-slack-feature',
1086
+ nodeType: 'slack.send_message',
1087
+ status: 'SKIPPED',
1088
+ inputs: {},
1089
+ outputs: undefined,
1090
+ startedAt: SWITCH_END,
1091
+ completedAt: SWITCH_END,
1092
+ duration: 0,
1093
+ retryCount: 0,
1094
+ },
1095
+ // 6. Incident path — skipped
1096
+ {
1097
+ id: 'nexec-pagerduty',
1098
+ flowRunId: 'run-triage-1',
1099
+ nodeId: 's-pagerduty',
1100
+ nodeType: 'http.request',
1101
+ status: 'SKIPPED',
1102
+ inputs: {},
1103
+ outputs: undefined,
1104
+ startedAt: SWITCH_END,
1105
+ completedAt: SWITCH_END,
1106
+ duration: 0,
1107
+ retryCount: 0,
1108
+ },
1109
+ // 7. Default path — skipped
1110
+ {
1111
+ id: 'nexec-slack-default',
1112
+ flowRunId: 'run-triage-1',
1113
+ nodeId: 's-slack-default',
1114
+ nodeType: 'slack.send_message',
1115
+ status: 'SKIPPED',
1116
+ inputs: {},
1117
+ outputs: undefined,
1118
+ startedAt: SWITCH_END,
1119
+ completedAt: SWITCH_END,
1120
+ duration: 0,
1121
+ retryCount: 0,
1122
+ },
1123
+ // 8. Update Linear Ticket — executes because bug branch (Create Fix PR) is live,
1124
+ // even though the other 3 source edges come from skipped nodes
1125
+ {
1126
+ id: 'nexec-linear-update',
1127
+ flowRunId: 'run-triage-1',
1128
+ nodeId: 's-linear-update',
1129
+ nodeType: 'linear.update_issue',
1130
+ status: 'SUCCESS',
1131
+ inputs: {
1132
+ create_fix_pr: prResult,
1133
+ },
1134
+ outputs: {
1135
+ nodeType: 'linear.update_issue',
1136
+ data: {
1137
+ variables: {
1138
+ output: {
1139
+ value: {
1140
+ id: 'LIN-4821',
1141
+ identifier: 'ENG-4821',
1142
+ state: { name: 'In Progress' },
1143
+ updatedAt: '2025-04-07T16:32:29.100Z',
1144
+ },
1145
+ type: 'object' as const,
1146
+ },
1147
+ },
1148
+ },
1149
+ },
1150
+ startedAt: LINEAR_UPDATE_START,
1151
+ completedAt: LINEAR_UPDATE_END,
1152
+ duration: 765,
1153
+ retryCount: 0,
1154
+ },
1155
+ ];
1156
+
1157
+ // ---------------------------------------------------------------------------
1158
+ // 5. Mock credentials used by the triage flow
1159
+ // ---------------------------------------------------------------------------
1160
+
1161
+ export const sampleCredentials = [
1162
+ {
1163
+ id: 'cred-anthropic',
1164
+ name: 'Anthropic — Production',
1165
+ type: 'llm' as const,
1166
+ authType: 'apiKey' as const,
1167
+ description: 'Claude API key for agent nodes',
1168
+ isActive: true,
1169
+ userId: 'demo-user',
1170
+ isShared: true,
1171
+ config: { apiKey: 'sk-ant-••••••••' },
1172
+ lastUsedAt: '2025-04-07T16:32:26Z',
1173
+ createdAt: '2025-01-10T09:00:00Z',
1174
+ updatedAt: '2025-03-15T11:20:00Z',
1175
+ },
1176
+ {
1177
+ id: 'cred-openai',
1178
+ name: 'OpenAI — Production',
1179
+ type: 'llm' as const,
1180
+ authType: 'apiKey' as const,
1181
+ description: 'GPT-4o key for model nodes',
1182
+ isActive: true,
1183
+ userId: 'demo-user',
1184
+ isShared: true,
1185
+ config: { apiKey: 'sk-proj-••••••••' },
1186
+ lastUsedAt: '2025-04-06T22:10:00Z',
1187
+ createdAt: '2025-01-10T09:05:00Z',
1188
+ updatedAt: '2025-02-20T14:00:00Z',
1189
+ },
1190
+ {
1191
+ id: 'cred-postgres',
1192
+ name: 'PostgreSQL — payment-db',
1193
+ type: 'database' as const,
1194
+ authType: 'connectionString' as const,
1195
+ description: 'Payment service database (read-only replica)',
1196
+ isActive: true,
1197
+ userId: 'demo-user',
1198
+ isShared: false,
1199
+ config: { connectionString: 'postgresql://readonly:••••@db.acme.internal:5432/payments' },
1200
+ lastUsedAt: '2025-04-07T16:32:11Z',
1201
+ createdAt: '2025-02-05T10:30:00Z',
1202
+ updatedAt: '2025-03-01T16:00:00Z',
1203
+ },
1204
+ {
1205
+ id: 'cred-github',
1206
+ name: 'GitHub — acme org',
1207
+ type: 'http-api' as const,
1208
+ authType: 'oauth2' as const,
1209
+ description: 'GitHub OAuth2 for repo access and PR creation',
1210
+ isActive: true,
1211
+ userId: 'demo-user',
1212
+ isShared: true,
1213
+ config: {
1214
+ oauth2Provider: 'github',
1215
+ accessToken: 'gho_••••••••',
1216
+ refreshToken: 'ghr_••••••••',
1217
+ tokenType: 'bearer',
1218
+ scope: 'repo,read:org',
1219
+ expiresAt: '2025-05-07T16:00:00Z',
1220
+ },
1221
+ lastUsedAt: '2025-04-07T16:32:28Z',
1222
+ createdAt: '2025-01-20T13:00:00Z',
1223
+ updatedAt: '2025-04-07T16:32:28Z',
1224
+ },
1225
+ {
1226
+ id: 'cred-slack',
1227
+ name: 'Slack — Acme Workspace',
1228
+ type: 'http-api' as const,
1229
+ authType: 'oauth2' as const,
1230
+ description: 'Slack bot for #triage and #product-requests channels',
1231
+ isActive: true,
1232
+ userId: 'demo-user',
1233
+ isShared: true,
1234
+ config: {
1235
+ oauth2Provider: 'slack',
1236
+ accessToken: 'xoxb-••••••••',
1237
+ tokenType: 'bearer',
1238
+ scope: 'chat:write,channels:read',
1239
+ },
1240
+ lastUsedAt: '2025-04-06T09:45:00Z',
1241
+ createdAt: '2025-01-25T11:00:00Z',
1242
+ updatedAt: '2025-03-10T08:30:00Z',
1243
+ },
1244
+ {
1245
+ id: 'cred-sentry',
1246
+ name: 'Sentry — acme org',
1247
+ type: 'http-api' as const,
1248
+ authType: 'bearer' as const,
1249
+ description: 'Sentry API token for issue search',
1250
+ isActive: true,
1251
+ userId: 'demo-user',
1252
+ isShared: false,
1253
+ config: { token: 'sntrys_••••••••' },
1254
+ lastUsedAt: '2025-04-07T16:32:14Z',
1255
+ createdAt: '2025-02-10T15:00:00Z',
1256
+ updatedAt: '2025-02-10T15:00:00Z',
1257
+ },
1258
+ {
1259
+ id: 'cred-aws',
1260
+ name: 'AWS — CloudWatch Logs',
1261
+ type: 'http-api' as const,
1262
+ authType: 'awsSigV4' as const,
1263
+ description: 'AWS credentials for CloudWatch Logs Insights queries',
1264
+ isActive: true,
1265
+ userId: 'demo-user',
1266
+ isShared: false,
1267
+ config: {
1268
+ accessKeyId: 'AKIA••••••••',
1269
+ secretAccessKey: '••••••••',
1270
+ region: 'us-east-1',
1271
+ service: 'logs',
1272
+ },
1273
+ lastUsedAt: '2025-04-07T16:32:18Z',
1274
+ createdAt: '2025-02-15T09:00:00Z',
1275
+ updatedAt: '2025-03-20T10:00:00Z',
1276
+ },
1277
+ {
1278
+ id: 'cred-notion',
1279
+ name: 'Notion — Acme Workspace',
1280
+ type: 'http-api' as const,
1281
+ authType: 'bearer' as const,
1282
+ description: 'Notion integration token for doc search',
1283
+ isActive: true,
1284
+ userId: 'demo-user',
1285
+ isShared: true,
1286
+ config: { token: 'ntn_••••••••' },
1287
+ lastUsedAt: '2025-04-07T16:32:20Z',
1288
+ createdAt: '2025-03-01T14:00:00Z',
1289
+ updatedAt: '2025-03-01T14:00:00Z',
1290
+ },
1291
+ {
1292
+ id: 'cred-pagerduty',
1293
+ name: 'PagerDuty — Events API',
1294
+ type: 'http-api' as const,
1295
+ authType: 'apiKey' as const,
1296
+ description: 'PagerDuty Events API v2 routing key',
1297
+ isActive: true,
1298
+ userId: 'demo-user',
1299
+ isShared: true,
1300
+ config: { apiKey: 'R0••••••••', paramName: 'routing_key' },
1301
+ lastUsedAt: '2025-03-28T03:15:00Z',
1302
+ createdAt: '2025-02-20T16:00:00Z',
1303
+ updatedAt: '2025-02-20T16:00:00Z',
1304
+ },
1305
+ ];
1306
+
1307
+ // ---------------------------------------------------------------------------
1308
+ // 6. Mock chat messages — assistant helped build the triage flow
1309
+ // ---------------------------------------------------------------------------
1310
+
1311
+ const T = (offset: number) =>
1312
+ new Date(Date.parse('2025-04-07T15:00:00Z') + offset * 1000).toISOString();
1313
+
1314
+ export const sampleChatMessages = [
1315
+ // --- Turn 1: User asks to build the flow ---
1316
+ {
1317
+ id: 'chat-1',
1318
+ flowId: 'flow-triage',
1319
+ role: 'user' as const,
1320
+ content:
1321
+ 'I want to build a ticket triage flow. When a Linear webhook comes in, an AI agent should investigate the ticket using our Postgres DB, Sentry, AWS CloudWatch logs, Notion docs, and GitHub. Then route it based on issue type — bug, feature request, or incident — to different handlers.',
1322
+ toolMeta: null,
1323
+ createdAt: T(0),
1324
+ },
1325
+
1326
+ // --- Assistant sets a plan ---
1327
+ {
1328
+ id: 'chat-2',
1329
+ flowId: 'flow-triage',
1330
+ role: 'tool' as const,
1331
+ content: '',
1332
+ toolMeta: {
1333
+ toolName: 'set_plan',
1334
+ args: {
1335
+ summary: 'Build a Linear ticket triage flow with AI investigation and multi-path routing',
1336
+ steps: [
1337
+ { index: 0, title: 'Add webhook trigger for Linear events', status: 'done' },
1338
+ { index: 1, title: 'Add AI agent node with investigation tools', status: 'done' },
1339
+ {
1340
+ index: 2,
1341
+ title: 'Configure agent tools: Postgres, Sentry, CloudWatch, Notion, GitHub',
1342
+ status: 'done',
1343
+ },
1344
+ { index: 3, title: 'Add switch node to route by issue type', status: 'done' },
1345
+ { index: 4, title: 'Add handler nodes for each branch', status: 'done' },
1346
+ { index: 5, title: 'Connect all nodes and validate flow', status: 'done' },
1347
+ ],
1348
+ },
1349
+ result: { success: true, data: { planSet: true } },
1350
+ status: 'done',
1351
+ startedAt: Date.parse(T(2)),
1352
+ durationMs: 45,
1353
+ },
1354
+ createdAt: T(2),
1355
+ },
1356
+
1357
+ // --- Assistant creates the flow ---
1358
+ {
1359
+ id: 'chat-3',
1360
+ flowId: 'flow-triage',
1361
+ role: 'tool' as const,
1362
+ content: '',
1363
+ toolMeta: {
1364
+ toolName: 'search_actions',
1365
+ args: { query: 'webhook trigger' },
1366
+ result: {
1367
+ success: true,
1368
+ data: {
1369
+ actions: [
1370
+ { id: 'trigger.webhook', name: 'Webhook Trigger', provider: 'Triggers' },
1371
+ { id: 'trigger.cron', name: 'Cron Trigger', provider: 'Triggers' },
1372
+ ],
1373
+ },
1374
+ },
1375
+ status: 'done',
1376
+ startedAt: Date.parse(T(3)),
1377
+ durationMs: 12,
1378
+ },
1379
+ createdAt: T(3),
1380
+ },
1381
+
1382
+ // --- Add webhook trigger ---
1383
+ {
1384
+ id: 'chat-4',
1385
+ flowId: 'flow-triage',
1386
+ role: 'tool' as const,
1387
+ content: '',
1388
+ toolMeta: {
1389
+ toolName: 'add_node',
1390
+ args: {
1391
+ type: 'trigger.webhook',
1392
+ name: 'Linear Webhook',
1393
+ referenceId: 'linear_webhook',
1394
+ },
1395
+ result: {
1396
+ success: true,
1397
+ data: { nodeId: 's-webhook', type: 'trigger.webhook', name: 'Linear Webhook' },
1398
+ },
1399
+ status: 'done',
1400
+ startedAt: Date.parse(T(4)),
1401
+ durationMs: 85,
1402
+ },
1403
+ createdAt: T(4),
1404
+ },
1405
+
1406
+ // --- Add agent node ---
1407
+ {
1408
+ id: 'chat-5',
1409
+ flowId: 'flow-triage',
1410
+ role: 'tool' as const,
1411
+ content: '',
1412
+ toolMeta: {
1413
+ toolName: 'add_node',
1414
+ args: {
1415
+ type: 'AGENT',
1416
+ name: 'Investigation Agent',
1417
+ referenceId: 'investigation_agent',
1418
+ },
1419
+ result: {
1420
+ success: true,
1421
+ data: { nodeId: 's-agent', type: 'AGENT', name: 'Investigation Agent' },
1422
+ },
1423
+ status: 'done',
1424
+ startedAt: Date.parse(T(5)),
1425
+ durationMs: 92,
1426
+ },
1427
+ createdAt: T(5),
1428
+ },
1429
+
1430
+ // --- Find credentials for agent ---
1431
+ {
1432
+ id: 'chat-6',
1433
+ flowId: 'flow-triage',
1434
+ role: 'tool' as const,
1435
+ content: '',
1436
+ toolMeta: {
1437
+ toolName: 'find_credentials_for_action',
1438
+ args: { actionId: 'AGENT' },
1439
+ result: {
1440
+ success: true,
1441
+ data: {
1442
+ credentials: [
1443
+ { id: 'cred-anthropic', name: 'Anthropic — Production', type: 'llm' },
1444
+ { id: 'cred-openai', name: 'OpenAI — Production', type: 'llm' },
1445
+ ],
1446
+ },
1447
+ },
1448
+ status: 'done',
1449
+ startedAt: Date.parse(T(6)),
1450
+ durationMs: 18,
1451
+ },
1452
+ createdAt: T(6),
1453
+ },
1454
+
1455
+ // --- Configure agent node ---
1456
+ {
1457
+ id: 'chat-7',
1458
+ flowId: 'flow-triage',
1459
+ role: 'tool' as const,
1460
+ content: '',
1461
+ toolMeta: {
1462
+ toolName: 'configure_agent',
1463
+ args: {
1464
+ nodeId: 's-agent',
1465
+ credentialId: 'cred-openai',
1466
+ model: 'gpt-4o',
1467
+ taskPrompt: 'Investigate Linear ticket "{{ linear_webhook.title }}"...',
1468
+ systemPrompt: 'You are a senior on-call engineer performing ticket triage.',
1469
+ maxIterations: 10,
1470
+ stopCondition: 'explicit_stop',
1471
+ },
1472
+ result: { success: true, data: { configured: true } },
1473
+ status: 'done',
1474
+ startedAt: Date.parse(T(7)),
1475
+ durationMs: 110,
1476
+ },
1477
+ createdAt: T(7),
1478
+ },
1479
+
1480
+ // --- Add tools to agent (batch of 5) ---
1481
+ {
1482
+ id: 'chat-8',
1483
+ flowId: 'flow-triage',
1484
+ role: 'tool' as const,
1485
+ content: '',
1486
+ toolMeta: {
1487
+ toolName: 'add_tool_to_agent',
1488
+ args: { nodeId: 's-agent', toolId: 'postgres.execute_query', name: 'Query Database' },
1489
+ result: { success: true, data: { instanceId: 'tool-pg', toolId: 'postgres.execute_query' } },
1490
+ status: 'done',
1491
+ startedAt: Date.parse(T(8)),
1492
+ durationMs: 65,
1493
+ },
1494
+ createdAt: T(8),
1495
+ },
1496
+ {
1497
+ id: 'chat-9',
1498
+ flowId: 'flow-triage',
1499
+ role: 'tool' as const,
1500
+ content: '',
1501
+ toolMeta: {
1502
+ toolName: 'add_tool_to_agent',
1503
+ args: { nodeId: 's-agent', toolId: 'sentry.list_issues', name: 'Sentry Issues' },
1504
+ result: {
1505
+ success: true,
1506
+ data: { instanceId: 'tool-sentry', toolId: 'sentry.list_issues' },
1507
+ },
1508
+ status: 'done',
1509
+ startedAt: Date.parse(T(9)),
1510
+ durationMs: 58,
1511
+ },
1512
+ createdAt: T(9),
1513
+ },
1514
+ {
1515
+ id: 'chat-10',
1516
+ flowId: 'flow-triage',
1517
+ role: 'tool' as const,
1518
+ content: '',
1519
+ toolMeta: {
1520
+ toolName: 'add_tool_to_agent',
1521
+ args: { nodeId: 's-agent', toolId: 'cloudwatch.start_query', name: 'AWS Log Insights' },
1522
+ result: {
1523
+ success: true,
1524
+ data: { instanceId: 'tool-aws', toolId: 'cloudwatch.start_query' },
1525
+ },
1526
+ status: 'done',
1527
+ startedAt: Date.parse(T(10)),
1528
+ durationMs: 62,
1529
+ },
1530
+ createdAt: T(10),
1531
+ },
1532
+ {
1533
+ id: 'chat-11',
1534
+ flowId: 'flow-triage',
1535
+ role: 'tool' as const,
1536
+ content: '',
1537
+ toolMeta: {
1538
+ toolName: 'add_tool_to_agent',
1539
+ args: { nodeId: 's-agent', toolId: 'notion.search', name: 'Search Notion' },
1540
+ result: { success: true, data: { instanceId: 'tool-notion', toolId: 'notion.search' } },
1541
+ status: 'done',
1542
+ startedAt: Date.parse(T(11)),
1543
+ durationMs: 55,
1544
+ },
1545
+ createdAt: T(11),
1546
+ },
1547
+ {
1548
+ id: 'chat-12',
1549
+ flowId: 'flow-triage',
1550
+ role: 'tool' as const,
1551
+ content: '',
1552
+ toolMeta: {
1553
+ toolName: 'add_tool_to_agent',
1554
+ args: { nodeId: 's-agent', toolId: 'github.get_file_content', name: 'Read Source File' },
1555
+ result: {
1556
+ success: true,
1557
+ data: { instanceId: 'tool-gh', toolId: 'github.get_file_content' },
1558
+ },
1559
+ status: 'done',
1560
+ startedAt: Date.parse(T(12)),
1561
+ durationMs: 60,
1562
+ },
1563
+ createdAt: T(12),
1564
+ },
1565
+
1566
+ // --- Assistant explains progress ---
1567
+ {
1568
+ id: 'chat-13',
1569
+ flowId: 'flow-triage',
1570
+ role: 'assistant' as const,
1571
+ content:
1572
+ "I've set up the webhook trigger and the investigation agent with all 5 tools. Now I'll add the switch node to route based on the issue type the agent identifies.",
1573
+ toolMeta: null,
1574
+ createdAt: T(13),
1575
+ },
1576
+
1577
+ // --- Add switch node ---
1578
+ {
1579
+ id: 'chat-14',
1580
+ flowId: 'flow-triage',
1581
+ role: 'tool' as const,
1582
+ content: '',
1583
+ toolMeta: {
1584
+ toolName: 'add_node',
1585
+ args: {
1586
+ type: 'core.switch',
1587
+ name: 'Route by Issue Type',
1588
+ referenceId: 'route_by_issue_type',
1589
+ params: {
1590
+ matchMode: 'first',
1591
+ cases: [
1592
+ { slug: 'bug', label: 'Bug', expression: 'investigation.issue_type === "bug"' },
1593
+ {
1594
+ slug: 'feature',
1595
+ label: 'Feature Request',
1596
+ expression: 'investigation.issue_type === "feature_request"',
1597
+ },
1598
+ {
1599
+ slug: 'incident',
1600
+ label: 'Incident',
1601
+ expression: 'investigation.issue_type === "incident"',
1602
+ },
1603
+ ],
1604
+ },
1605
+ },
1606
+ result: { success: true, data: { nodeId: 's-switch', type: 'core.switch' } },
1607
+ status: 'done',
1608
+ startedAt: Date.parse(T(14)),
1609
+ durationMs: 95,
1610
+ },
1611
+ createdAt: T(14),
1612
+ },
1613
+
1614
+ // --- Add handler nodes ---
1615
+ {
1616
+ id: 'chat-15',
1617
+ flowId: 'flow-triage',
1618
+ role: 'tool' as const,
1619
+ content: '',
1620
+ toolMeta: {
1621
+ toolName: 'add_node',
1622
+ args: {
1623
+ type: 'github.create_pull_request',
1624
+ name: 'Create Fix PR',
1625
+ referenceId: 'create_fix_pr',
1626
+ },
1627
+ result: { success: true, data: { nodeId: 's-gh-pr' } },
1628
+ status: 'done',
1629
+ startedAt: Date.parse(T(15)),
1630
+ durationMs: 78,
1631
+ },
1632
+ createdAt: T(15),
1633
+ },
1634
+ {
1635
+ id: 'chat-16',
1636
+ flowId: 'flow-triage',
1637
+ role: 'tool' as const,
1638
+ content: '',
1639
+ toolMeta: {
1640
+ toolName: 'add_node',
1641
+ args: {
1642
+ type: 'slack.send_message',
1643
+ name: 'Notify #product',
1644
+ referenceId: 'notify_product',
1645
+ },
1646
+ result: { success: true, data: { nodeId: 's-slack-feature' } },
1647
+ status: 'done',
1648
+ startedAt: Date.parse(T(16)),
1649
+ durationMs: 72,
1650
+ },
1651
+ createdAt: T(16),
1652
+ },
1653
+ {
1654
+ id: 'chat-17',
1655
+ flowId: 'flow-triage',
1656
+ role: 'tool' as const,
1657
+ content: '',
1658
+ toolMeta: {
1659
+ toolName: 'add_node',
1660
+ args: {
1661
+ type: 'http.request',
1662
+ name: 'PagerDuty Alert',
1663
+ referenceId: 'pagerduty_alert',
1664
+ },
1665
+ result: { success: true, data: { nodeId: 's-pagerduty' } },
1666
+ status: 'done',
1667
+ startedAt: Date.parse(T(17)),
1668
+ durationMs: 68,
1669
+ },
1670
+ createdAt: T(17),
1671
+ },
1672
+ {
1673
+ id: 'chat-18',
1674
+ flowId: 'flow-triage',
1675
+ role: 'tool' as const,
1676
+ content: '',
1677
+ toolMeta: {
1678
+ toolName: 'add_node',
1679
+ args: {
1680
+ type: 'slack.send_message',
1681
+ name: 'Notify #triage',
1682
+ referenceId: 'notify_triage',
1683
+ },
1684
+ result: { success: true, data: { nodeId: 's-slack-default' } },
1685
+ status: 'done',
1686
+ startedAt: Date.parse(T(18)),
1687
+ durationMs: 70,
1688
+ },
1689
+ createdAt: T(18),
1690
+ },
1691
+
1692
+ // --- Connect all nodes ---
1693
+ {
1694
+ id: 'chat-19',
1695
+ flowId: 'flow-triage',
1696
+ role: 'tool' as const,
1697
+ content: '',
1698
+ toolMeta: {
1699
+ toolName: 'connect_nodes',
1700
+ args: { sourceId: 's-webhook', targetId: 's-agent' },
1701
+ result: { success: true, data: { edgeId: 'se-webhook-agent' } },
1702
+ status: 'done',
1703
+ startedAt: Date.parse(T(19)),
1704
+ durationMs: 30,
1705
+ },
1706
+ createdAt: T(19),
1707
+ },
1708
+ {
1709
+ id: 'chat-20',
1710
+ flowId: 'flow-triage',
1711
+ role: 'tool' as const,
1712
+ content: '',
1713
+ toolMeta: {
1714
+ toolName: 'connect_nodes',
1715
+ args: { sourceId: 's-agent', targetId: 's-switch' },
1716
+ result: { success: true, data: { edgeId: 'se-agent-switch' } },
1717
+ status: 'done',
1718
+ startedAt: Date.parse(T(20)),
1719
+ durationMs: 28,
1720
+ },
1721
+ createdAt: T(20),
1722
+ },
1723
+ {
1724
+ id: 'chat-21',
1725
+ flowId: 'flow-triage',
1726
+ role: 'tool' as const,
1727
+ content: '',
1728
+ toolMeta: {
1729
+ toolName: 'connect_nodes',
1730
+ args: { sourceId: 's-switch', targetId: 's-gh-pr', sourceHandle: 'bug' },
1731
+ result: { success: true, data: { edgeId: 'se-switch-pr' } },
1732
+ status: 'done',
1733
+ startedAt: Date.parse(T(21)),
1734
+ durationMs: 25,
1735
+ },
1736
+ createdAt: T(21),
1737
+ },
1738
+ {
1739
+ id: 'chat-22',
1740
+ flowId: 'flow-triage',
1741
+ role: 'tool' as const,
1742
+ content: '',
1743
+ toolMeta: {
1744
+ toolName: 'connect_nodes',
1745
+ args: { sourceId: 's-switch', targetId: 's-slack-feature', sourceHandle: 'feature' },
1746
+ result: { success: true, data: { edgeId: 'se-switch-feature' } },
1747
+ status: 'done',
1748
+ startedAt: Date.parse(T(22)),
1749
+ durationMs: 26,
1750
+ },
1751
+ createdAt: T(22),
1752
+ },
1753
+ {
1754
+ id: 'chat-23',
1755
+ flowId: 'flow-triage',
1756
+ role: 'tool' as const,
1757
+ content: '',
1758
+ toolMeta: {
1759
+ toolName: 'connect_nodes',
1760
+ args: { sourceId: 's-switch', targetId: 's-pagerduty', sourceHandle: 'incident' },
1761
+ result: { success: true, data: { edgeId: 'se-switch-incident' } },
1762
+ status: 'done',
1763
+ startedAt: Date.parse(T(23)),
1764
+ durationMs: 24,
1765
+ },
1766
+ createdAt: T(23),
1767
+ },
1768
+ {
1769
+ id: 'chat-24',
1770
+ flowId: 'flow-triage',
1771
+ role: 'tool' as const,
1772
+ content: '',
1773
+ toolMeta: {
1774
+ toolName: 'connect_nodes',
1775
+ args: { sourceId: 's-switch', targetId: 's-slack-default', sourceHandle: 'default' },
1776
+ result: { success: true, data: { edgeId: 'se-switch-default' } },
1777
+ status: 'done',
1778
+ startedAt: Date.parse(T(24)),
1779
+ durationMs: 27,
1780
+ },
1781
+ createdAt: T(24),
1782
+ },
1783
+
1784
+ // --- Validate flow ---
1785
+ {
1786
+ id: 'chat-25',
1787
+ flowId: 'flow-triage',
1788
+ role: 'tool' as const,
1789
+ content: '',
1790
+ toolMeta: {
1791
+ toolName: 'validate_flow',
1792
+ args: {},
1793
+ result: { success: true, data: { isValid: true, errors: [], warnings: [] } },
1794
+ status: 'done',
1795
+ startedAt: Date.parse(T(25)),
1796
+ durationMs: 140,
1797
+ },
1798
+ createdAt: T(25),
1799
+ },
1800
+
1801
+ // --- Update plan to mark all done ---
1802
+ {
1803
+ id: 'chat-26',
1804
+ flowId: 'flow-triage',
1805
+ role: 'tool' as const,
1806
+ content: '',
1807
+ toolMeta: {
1808
+ toolName: 'update_plan',
1809
+ args: {
1810
+ steps: [
1811
+ { index: 0, status: 'done' },
1812
+ { index: 1, status: 'done' },
1813
+ { index: 2, status: 'done' },
1814
+ { index: 3, status: 'done' },
1815
+ { index: 4, status: 'done' },
1816
+ { index: 5, status: 'done' },
1817
+ ],
1818
+ },
1819
+ result: { success: true, data: { updated: true } },
1820
+ status: 'done',
1821
+ startedAt: Date.parse(T(26)),
1822
+ durationMs: 15,
1823
+ },
1824
+ createdAt: T(26),
1825
+ },
1826
+
1827
+ // --- Final assistant message ---
1828
+ {
1829
+ id: 'chat-27',
1830
+ flowId: 'flow-triage',
1831
+ role: 'assistant' as const,
1832
+ content:
1833
+ "Your Linear ticket triage flow is ready! Here's what I built:\n\n" +
1834
+ '1. **Linear Webhook** — receives incoming ticket events\n' +
1835
+ '2. **Investigation Agent** — an AI agent (GPT-4o) that queries your Postgres DB, searches Sentry for errors, checks AWS CloudWatch logs, searches Notion for runbooks, and reads source files on GitHub to produce a root cause analysis with severity rating\n' +
1836
+ "3. **Route by Issue Type** — routes based on the agent's classification:\n" +
1837
+ ' - **Bug** → Creates a fix PR on GitHub\n' +
1838
+ ' - **Feature Request** → Notifies #product-requests on Slack\n' +
1839
+ ' - **Incident** → Triggers a PagerDuty incident for escalation\n' +
1840
+ ' - **Default** → Notifies #triage on Slack for manual review\n\n' +
1841
+ "The flow validated successfully. You can test it by sending a sample Linear webhook payload, or set up a real webhook in your Linear workspace settings pointing to this flow's trigger URL.",
1842
+ toolMeta: null,
1843
+ createdAt: T(28),
1844
+ },
1845
+
1846
+ // --- User asks a follow-up ---
1847
+ {
1848
+ id: 'chat-28',
1849
+ flowId: 'flow-triage',
1850
+ role: 'user' as const,
1851
+ content: 'Can you run it with a test payload to make sure everything works?',
1852
+ toolMeta: null,
1853
+ createdAt: T(60),
1854
+ },
1855
+
1856
+ // --- Assistant runs the flow ---
1857
+ {
1858
+ id: 'chat-29',
1859
+ flowId: 'flow-triage',
1860
+ role: 'tool' as const,
1861
+ content: '',
1862
+ toolMeta: {
1863
+ toolName: 'run_flow',
1864
+ args: {
1865
+ inputs: {
1866
+ action: 'create',
1867
+ type: 'Issue',
1868
+ data: {
1869
+ id: 'LIN-4821',
1870
+ identifier: 'ENG-4821',
1871
+ title: 'Payment processing fails with 502 for Stripe webhook handler',
1872
+ priority: 1,
1873
+ team: { key: 'ENG' },
1874
+ labels: [{ name: 'bug' }, { name: 'payments' }],
1875
+ },
1876
+ },
1877
+ },
1878
+ result: {
1879
+ success: true,
1880
+ data: {
1881
+ flowRunId: 'run-triage-1',
1882
+ status: 'SUCCESS',
1883
+ duration: 18345,
1884
+ outputs: {
1885
+ fix_pr: { number: 4293, html_url: 'https://github.com/acme/platform/pull/4293' },
1886
+ },
1887
+ },
1888
+ },
1889
+ status: 'done',
1890
+ startedAt: Date.parse(T(62)),
1891
+ durationMs: 18400,
1892
+ },
1893
+ createdAt: T(62),
1894
+ },
1895
+
1896
+ // --- Final confirmation ---
1897
+ {
1898
+ id: 'chat-30',
1899
+ flowId: 'flow-triage',
1900
+ role: 'assistant' as const,
1901
+ content:
1902
+ "The test run completed successfully in 18.3 seconds. Here's what happened:\n\n" +
1903
+ '- The agent investigated the Stripe webhook 502 issue across all 5 data sources\n' +
1904
+ '- It identified a **connection pool exhaustion bug** in `stripe-handler.ts` (missing `finally` block for connection release)\n' +
1905
+ '- The switch node correctly classified it as a **bug**\n' +
1906
+ '- A fix PR was created: [acme/platform#4293](https://github.com/acme/platform/pull/4293)\n\n' +
1907
+ 'The skipped branches (feature request, incident, default) behaved correctly — only the bug path executed. You can view the full execution details in the Flow Runs tab.',
1908
+ toolMeta: null,
1909
+ createdAt: T(82),
1910
+ },
1911
+ ];
1912
+
1913
+ // ---------------------------------------------------------------------------
1914
+ // 7. Complete DemoData bundle — ready for <DemoInvect>
1915
+ // ---------------------------------------------------------------------------
1916
+
1917
+ // The DemoData types (ReactFlowData, Flow) come from core DB types which
1918
+ // are stricter than what static sample data needs. We build a loose object
1919
+ // and cast once at the boundary — the mock client only serialises values.
1920
+ export const sampleDemoData: DemoData = {
1921
+ flows: [
1922
+ {
1923
+ id: 'flow-triage',
1924
+ name: 'Linear Ticket Triage',
1925
+ description: 'AI-powered ticket investigation with multi-path routing',
1926
+ isActive: true,
1927
+ createdAt: '2025-03-10T12:00:00Z',
1928
+ updatedAt: '2025-04-01T16:45:00Z',
1929
+ },
1930
+ {
1931
+ id: 'flow-simple',
1932
+ name: 'Text Summarizer',
1933
+ description: 'Summarizes user input text using GPT-4o',
1934
+ isActive: true,
1935
+ createdAt: '2025-01-15T10:00:00Z',
1936
+ updatedAt: '2025-03-20T14:30:00Z',
1937
+ },
1938
+ {
1939
+ id: 'flow-branching',
1940
+ name: 'Priority Router',
1941
+ description: 'Routes incoming webhooks based on priority level',
1942
+ isActive: true,
1943
+ createdAt: '2025-02-01T08:00:00Z',
1944
+ updatedAt: '2025-03-25T09:15:00Z',
1945
+ },
1946
+ ] as DemoData['flows'],
1947
+ flowReactFlowData: {
1948
+ 'flow-triage': {
1949
+ nodes: showcaseFlowNodes,
1950
+ edges: showcaseFlowEdges,
1951
+ version: { flowId: 'flow-triage', version: 1 },
1952
+ name: 'Linear Ticket Triage',
1953
+ isActive: true,
1954
+ },
1955
+ 'flow-simple': {
1956
+ nodes: simpleFlowNodes,
1957
+ edges: simpleFlowEdges,
1958
+ version: { flowId: 'flow-simple', version: 1 },
1959
+ name: 'Text Summarizer',
1960
+ isActive: true,
1961
+ },
1962
+ 'flow-branching': {
1963
+ nodes: branchingFlowNodes,
1964
+ edges: branchingFlowEdges,
1965
+ version: { flowId: 'flow-branching', version: 1 },
1966
+ name: 'Priority Router',
1967
+ isActive: true,
1968
+ },
1969
+ } as unknown as DemoData['flowReactFlowData'],
1970
+ nodeDefinitions: sampleNodeDefinitions,
1971
+ agentTools: showcaseAgentTools as unknown as DemoData['agentTools'],
1972
+ flowRuns: [showcaseFlowRun] as unknown as DemoData['flowRuns'],
1973
+ nodeExecutions: {
1974
+ 'run-triage-1': showcaseNodeExecutions,
1975
+ } as unknown as DemoData['nodeExecutions'],
1976
+ credentials: sampleCredentials as unknown as DemoData['credentials'],
1977
+ chatMessages: {
1978
+ 'flow-triage': sampleChatMessages,
1979
+ },
1980
+ };