sea-dev 1.0.0

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 (784) hide show
  1. package/.claude/tasks/README.md +89 -0
  2. package/.cursor/rules/commits.mdc +31 -0
  3. package/.cursor/rules/general.mdc +84 -0
  4. package/.github/workflows/ci-cd.yml +141 -0
  5. package/CLAUDE.md +337 -0
  6. package/README.md +129 -0
  7. package/apps/api/.prettierignore +6 -0
  8. package/apps/api/.prettierrc.js +3 -0
  9. package/apps/api/dotenvx-safe.sh +11 -0
  10. package/apps/api/eslint.config.mjs +3 -0
  11. package/apps/api/package.json +58 -0
  12. package/apps/api/src/clients/posthog.ts +25 -0
  13. package/apps/api/src/dal/submission.ts +59 -0
  14. package/apps/api/src/errors.ts +55 -0
  15. package/apps/api/src/index.ts +21 -0
  16. package/apps/api/src/lib/channel.ts +28 -0
  17. package/apps/api/src/lib/config.ts +9 -0
  18. package/apps/api/src/lib/fmt.test.ts +9 -0
  19. package/apps/api/src/lib/fmt.ts +62 -0
  20. package/apps/api/src/lib/invariant.ts +23 -0
  21. package/apps/api/src/middleware/auth.ts +66 -0
  22. package/apps/api/src/routes/index.ts +20 -0
  23. package/apps/api/src/routes/v2/chat/handlers.ts +693 -0
  24. package/apps/api/src/routes/v2/chat/index.ts +257 -0
  25. package/apps/api/src/routes/v2/chat/schemas.ts +43 -0
  26. package/apps/api/src/routes/v2/deals/handlers.ts +64 -0
  27. package/apps/api/src/routes/v2/deals/index.ts +88 -0
  28. package/apps/api/src/routes/v2/deals/schemas.ts +38 -0
  29. package/apps/api/src/routes/v2/forms/handlers.ts +415 -0
  30. package/apps/api/src/routes/v2/forms/index.ts +382 -0
  31. package/apps/api/src/routes/v2/forms/schemas.ts +243 -0
  32. package/apps/api/src/routes/v2/index.ts +19 -0
  33. package/apps/api/src/routes/v2/pipelines/handlers.ts +261 -0
  34. package/apps/api/src/routes/v2/pipelines/index.ts +224 -0
  35. package/apps/api/src/routes/v2/pipelines/schemas.ts +173 -0
  36. package/apps/api/src/routes/v2/submissions/handlers.ts +555 -0
  37. package/apps/api/src/routes/v2/submissions/index.ts +366 -0
  38. package/apps/api/src/routes/v2/submissions/schemas.ts +233 -0
  39. package/apps/api/src/routes/v2/workflows/handlers.ts +81 -0
  40. package/apps/api/src/routes/v2/workflows/index.ts +88 -0
  41. package/apps/api/src/routes/v2/workflows/schemas.ts +40 -0
  42. package/apps/api/src/server.ts +146 -0
  43. package/apps/api/src/static/favicon.ico +0 -0
  44. package/apps/api/src/types/api.ts +14 -0
  45. package/apps/api/src/types/result.ts +3 -0
  46. package/apps/api/tsconfig.json +22 -0
  47. package/apps/api/vite.config.ts +28 -0
  48. package/apps/api/vitest.config.ts +14 -0
  49. package/apps/conversion-worker/Dockerfile +59 -0
  50. package/apps/conversion-worker/package.json +31 -0
  51. package/apps/conversion-worker/src/lib/config.ts +7 -0
  52. package/apps/conversion-worker/src/main.ts +22 -0
  53. package/apps/conversion-worker/src/workflows/convert-pptx.ts +116 -0
  54. package/apps/conversion-worker/tsconfig.json +27 -0
  55. package/apps/conversion-worker/vite.config.ts +33 -0
  56. package/apps/main/.prettierignore +6 -0
  57. package/apps/main/.prettierrc.js +3 -0
  58. package/apps/main/CLAUDE.md +245 -0
  59. package/apps/main/Procfile +1 -0
  60. package/apps/main/README.md +193 -0
  61. package/apps/main/db-tests.jsonl +116 -0
  62. package/apps/main/dotenvx-safe.sh +11 -0
  63. package/apps/main/drizzle/meta/_journal.json +1 -0
  64. package/apps/main/drizzle.config.ts +25 -0
  65. package/apps/main/eslint.config.mjs +3 -0
  66. package/apps/main/generate-routes.mjs +5 -0
  67. package/apps/main/package.json +131 -0
  68. package/apps/main/playwright.config.ts +23 -0
  69. package/apps/main/postcss.config.ts +5 -0
  70. package/apps/main/public/bg-dark.svg +10 -0
  71. package/apps/main/public/bg.svg +10 -0
  72. package/apps/main/public/favicon.ico +0 -0
  73. package/apps/main/run.sh +146 -0
  74. package/apps/main/scripts/browser.ts +14 -0
  75. package/apps/main/scripts/db-test-cov.ts +277 -0
  76. package/apps/main/scripts/login.ts +78 -0
  77. package/apps/main/scripts/repl.ts +61 -0
  78. package/apps/main/src/_foo.ts +31 -0
  79. package/apps/main/src/_tests/db.test.ts +19 -0
  80. package/apps/main/src/_tests/mock-db.ts +60 -0
  81. package/apps/main/src/client.tsx +13 -0
  82. package/apps/main/src/clients/loops.ts +13 -0
  83. package/apps/main/src/clients/polar.ts +12 -0
  84. package/apps/main/src/clients/posthog.ts +12 -0
  85. package/apps/main/src/components/chat/chat-context.tsx +99 -0
  86. package/apps/main/src/components/chat/chat-messages.tsx +184 -0
  87. package/apps/main/src/components/chat/chat-status.tsx +140 -0
  88. package/apps/main/src/components/chat/chat.tsx +458 -0
  89. package/apps/main/src/components/chat/citation-modal.tsx +54 -0
  90. package/apps/main/src/components/cta.tsx +21 -0
  91. package/apps/main/src/components/data-display/derived.tsx +40 -0
  92. package/apps/main/src/components/data-display/group-single.tsx +57 -0
  93. package/apps/main/src/components/data-display/group-table.tsx +165 -0
  94. package/apps/main/src/components/data-display/group-wrapper.tsx +54 -0
  95. package/apps/main/src/components/data-display/item.tsx +678 -0
  96. package/apps/main/src/components/error.tsx +45 -0
  97. package/apps/main/src/components/forms/error.tsx +22 -0
  98. package/apps/main/src/components/grid.tsx +7 -0
  99. package/apps/main/src/components/header/container.tsx +73 -0
  100. package/apps/main/src/components/header/header-bar.tsx +102 -0
  101. package/apps/main/src/components/modals/copy-display.tsx +37 -0
  102. package/apps/main/src/components/modals/copy-form.tsx +152 -0
  103. package/apps/main/src/components/modals/duplicate-workflow.tsx +89 -0
  104. package/apps/main/src/components/modals/field-correction.tsx +323 -0
  105. package/apps/main/src/components/modals/form-viewer.tsx +126 -0
  106. package/apps/main/src/components/modals/modals.tsx +44 -0
  107. package/apps/main/src/components/modals/new-deal.tsx +78 -0
  108. package/apps/main/src/components/modals/new-form.tsx +133 -0
  109. package/apps/main/src/components/modals/new-pipeline.tsx +70 -0
  110. package/apps/main/src/components/modals/new-submission.tsx +321 -0
  111. package/apps/main/src/components/modals/new-workflow.tsx +342 -0
  112. package/apps/main/src/components/modals/transformation-sources-modal.tsx +157 -0
  113. package/apps/main/src/components/modals/view-report.tsx +193 -0
  114. package/apps/main/src/components/not-found.tsx +14 -0
  115. package/apps/main/src/components/search/search-bar.tsx +178 -0
  116. package/apps/main/src/components/sheet-selector.tsx +135 -0
  117. package/apps/main/src/components/side-panel/doc-list.tsx +480 -0
  118. package/apps/main/src/components/sidebar/admin-sidebar.tsx +75 -0
  119. package/apps/main/src/components/sidebar/app-sidebar.tsx +417 -0
  120. package/apps/main/src/components/sidebar/model-select.tsx +134 -0
  121. package/apps/main/src/components/sidebar/settings-sidebar.tsx +132 -0
  122. package/apps/main/src/components/sidebar/sidebar-right.tsx +22 -0
  123. package/apps/main/src/components/sidebar/stop-impersonate.tsx +21 -0
  124. package/apps/main/src/components/svg/loading.tsx +33 -0
  125. package/apps/main/src/components/theme-selector.tsx +43 -0
  126. package/apps/main/src/components/unsaved-badge.tsx +19 -0
  127. package/apps/main/src/components/upload/file-upload.tsx +354 -0
  128. package/apps/main/src/fns/submission-groups.ts +28 -0
  129. package/apps/main/src/fns/submission-items.ts +11 -0
  130. package/apps/main/src/global-middleware.ts +16 -0
  131. package/apps/main/src/hooks/use-update-state.ts +18 -0
  132. package/apps/main/src/lib/auth-client.ts +16 -0
  133. package/apps/main/src/lib/auth.test.ts +359 -0
  134. package/apps/main/src/lib/auth.ts +144 -0
  135. package/apps/main/src/lib/billing.ts +23 -0
  136. package/apps/main/src/lib/config-iso.ts +76 -0
  137. package/apps/main/src/lib/config.ts +61 -0
  138. package/apps/main/src/lib/excel.ts +16 -0
  139. package/apps/main/src/lib/feedback-cache.ts +70 -0
  140. package/apps/main/src/lib/logger.ts +44 -0
  141. package/apps/main/src/lib/models.ts +22 -0
  142. package/apps/main/src/lib/not-found.ts +17 -0
  143. package/apps/main/src/lib/pdf.ts +16 -0
  144. package/apps/main/src/lib/tabularize.ts +54 -0
  145. package/apps/main/src/lib/utils.ts +10 -0
  146. package/apps/main/src/lib/zfd.ts +217 -0
  147. package/apps/main/src/middleware.ts +55 -0
  148. package/apps/main/src/routeTree.gen.ts +1255 -0
  149. package/apps/main/src/router.tsx +24 -0
  150. package/apps/main/src/routes/__root.tsx +92 -0
  151. package/apps/main/src/routes/_authed/_app/(dashboard)/index.tsx +227 -0
  152. package/apps/main/src/routes/_authed/_app/agents/$agentId/config.tsx +224 -0
  153. package/apps/main/src/routes/_authed/_app/agents/$agentId/index.tsx +206 -0
  154. package/apps/main/src/routes/_authed/_app/agents/-components/agent-actions-menu.tsx +94 -0
  155. package/apps/main/src/routes/_authed/_app/agents/-components/agent-artifacts.tsx +153 -0
  156. package/apps/main/src/routes/_authed/_app/agents/-components/agent-chat.tsx +220 -0
  157. package/apps/main/src/routes/_authed/_app/agents/-components/agent-history-menu.tsx +81 -0
  158. package/apps/main/src/routes/_authed/_app/agents/-components/agent-model-select.tsx +84 -0
  159. package/apps/main/src/routes/_authed/_app/agents/-components/agent-relevant-items.tsx +226 -0
  160. package/apps/main/src/routes/_authed/_app/agents/-components/agent-upload-button.tsx +298 -0
  161. package/apps/main/src/routes/_authed/_app/agents/-components/context-modal.tsx +187 -0
  162. package/apps/main/src/routes/_authed/_app/agents/-fns.ts +560 -0
  163. package/apps/main/src/routes/_authed/_app/agents/index.tsx +65 -0
  164. package/apps/main/src/routes/_authed/_app/deals/$dealId/$subId/-components/citation-tree.tsx +268 -0
  165. package/apps/main/src/routes/_authed/_app/deals/$dealId/$subId.tsx +655 -0
  166. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/doc-loading.tsx +37 -0
  167. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/share-link.tsx +42 -0
  168. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submission-card.tsx +89 -0
  169. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submission-filter.tsx +193 -0
  170. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/submissions.tsx +36 -0
  171. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/summary.tsx +82 -0
  172. package/apps/main/src/routes/_authed/_app/deals/$dealId/-components/upload-doc.tsx +120 -0
  173. package/apps/main/src/routes/_authed/_app/deals/$dealId/-fns.ts +653 -0
  174. package/apps/main/src/routes/_authed/_app/deals/$dealId/index.tsx +259 -0
  175. package/apps/main/src/routes/_authed/_app/deals/$dealId/route.tsx +29 -0
  176. package/apps/main/src/routes/_authed/_app/deals/index.tsx +104 -0
  177. package/apps/main/src/routes/_authed/_app/feedback/index.tsx +639 -0
  178. package/apps/main/src/routes/_authed/_app/feedback/insights.tsx +250 -0
  179. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/blockers-panel.tsx +260 -0
  180. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/manual-input-panel.tsx +301 -0
  181. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/submission-selector-modal.tsx +143 -0
  182. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/-components/upload-doc.tsx +120 -0
  183. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/$runId/index.tsx +1485 -0
  184. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/-components/dag-view.tsx +296 -0
  185. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/-components/step-config-modal.tsx +634 -0
  186. package/apps/main/src/routes/_authed/_app/pipelines/$pipelineId/index.tsx +911 -0
  187. package/apps/main/src/routes/_authed/_app/pipelines/-fns.ts +510 -0
  188. package/apps/main/src/routes/_authed/_app/pipelines/index.tsx +103 -0
  189. package/apps/main/src/routes/_authed/_app/reports/$reportId.tsx +397 -0
  190. package/apps/main/src/routes/_authed/_app/reports/-fns.ts +11 -0
  191. package/apps/main/src/routes/_authed/_app/reports/index.tsx +22 -0
  192. package/apps/main/src/routes/_authed/_app/route.tsx +48 -0
  193. package/apps/main/src/routes/_authed/_app/submissions/-columns.tsx +161 -0
  194. package/apps/main/src/routes/_authed/_app/submissions/-fns.ts +128 -0
  195. package/apps/main/src/routes/_authed/_app/submissions/index.tsx +190 -0
  196. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/$formId.tsx +542 -0
  197. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/derived.tsx +154 -0
  198. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/field.tsx +369 -0
  199. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/-components/group.tsx +475 -0
  200. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/index.tsx +263 -0
  201. package/apps/main/src/routes/_authed/_app/workflows/$wfSlug/route.tsx +33 -0
  202. package/apps/main/src/routes/_authed/_app/workflows/-components/form-card.tsx +315 -0
  203. package/apps/main/src/routes/_authed/_app/workflows/index.tsx +86 -0
  204. package/apps/main/src/routes/_authed/admin/index.tsx +12 -0
  205. package/apps/main/src/routes/_authed/admin/route.tsx +42 -0
  206. package/apps/main/src/routes/_authed/admin/users/-columns.tsx +124 -0
  207. package/apps/main/src/routes/_authed/admin/users/-fns.ts +30 -0
  208. package/apps/main/src/routes/_authed/admin/users/index.tsx +29 -0
  209. package/apps/main/src/routes/_authed/catchNotFound.tsx +114 -0
  210. package/apps/main/src/routes/_authed/redirects/forms.$id.tsx +29 -0
  211. package/apps/main/src/routes/_authed/redirects/submissions.$id.tsx +27 -0
  212. package/apps/main/src/routes/_authed/redirects/workflows.$id.tsx +27 -0
  213. package/apps/main/src/routes/_authed/route.tsx +51 -0
  214. package/apps/main/src/routes/_authed/settings/-components/new-api-key.tsx +85 -0
  215. package/apps/main/src/routes/_authed/settings/-components/new-invite.tsx +100 -0
  216. package/apps/main/src/routes/_authed/settings/analytics.tsx +1710 -0
  217. package/apps/main/src/routes/_authed/settings/billing/-components/price-table.tsx +129 -0
  218. package/apps/main/src/routes/_authed/settings/billing/-fns.ts +76 -0
  219. package/apps/main/src/routes/_authed/settings/billing/index.tsx +119 -0
  220. package/apps/main/src/routes/_authed/settings/embed.tsx +337 -0
  221. package/apps/main/src/routes/_authed/settings/index.tsx +12 -0
  222. package/apps/main/src/routes/_authed/settings/keys.tsx +157 -0
  223. package/apps/main/src/routes/_authed/settings/members.tsx +276 -0
  224. package/apps/main/src/routes/_authed/settings/route.tsx +22 -0
  225. package/apps/main/src/routes/_authed/settings/user.tsx +87 -0
  226. package/apps/main/src/routes/_authed/settings/workspace.tsx +206 -0
  227. package/apps/main/src/routes/_public/-components/sign-in-up.tsx +96 -0
  228. package/apps/main/src/routes/_public/embedded.tsx +57 -0
  229. package/apps/main/src/routes/_public/invite.$inviteId.tsx +143 -0
  230. package/apps/main/src/routes/_public/no-access.tsx +38 -0
  231. package/apps/main/src/routes/_public/no-invite.tsx +39 -0
  232. package/apps/main/src/routes/_public/otp.tsx +103 -0
  233. package/apps/main/src/routes/_public/route.tsx +15 -0
  234. package/apps/main/src/routes/_public/sign-in.tsx +111 -0
  235. package/apps/main/src/routes/_public/sign-up.tsx +114 -0
  236. package/apps/main/src/routes/api/auth/$.ts +11 -0
  237. package/apps/main/src/routes/api/billing/paid.ts +42 -0
  238. package/apps/main/src/routes/api/billing/webhooks.ts +70 -0
  239. package/apps/main/src/routes/api/chat/agent.ts +40 -0
  240. package/apps/main/src/routes/api/chat/key.ts +42 -0
  241. package/apps/main/src/routes/api/chat/member.ts +35 -0
  242. package/apps/main/src/routes/api/test/index.ts +19 -0
  243. package/apps/main/src/server.tsx +6 -0
  244. package/apps/main/src/styles/app.css +23 -0
  245. package/apps/main/src/vite-env.d.ts +7 -0
  246. package/apps/main/test.http +6 -0
  247. package/apps/main/tsconfig.json +17 -0
  248. package/apps/main/vite.config.ts +24 -0
  249. package/apps/main/vitest.config.js +17 -0
  250. package/apps/mcp/README.md +171 -0
  251. package/apps/mcp/eslint.config.mjs +3 -0
  252. package/apps/mcp/package.json +37 -0
  253. package/apps/mcp/src/index.ts +414 -0
  254. package/apps/mcp/tsconfig.json +19 -0
  255. package/apps/mcp/vite.config.ts +22 -0
  256. package/apps/posthog-proxy/index.html +9 -0
  257. package/apps/workers/.prettierignore +7 -0
  258. package/apps/workers/.prettierrc.js +3 -0
  259. package/apps/workers/dotenvx-safe.sh +11 -0
  260. package/apps/workers/eslint.config.mjs +3 -0
  261. package/apps/workers/package.json +65 -0
  262. package/apps/workers/src/lib/config.ts +7 -0
  263. package/apps/workers/src/lib/messages.ts +0 -0
  264. package/apps/workers/src/lib/posthog.ts +25 -0
  265. package/apps/workers/src/main.ts +58 -0
  266. package/apps/workers/src/workflows/extraction.ts +866 -0
  267. package/apps/workers/src/workflows/index.ts +3 -0
  268. package/apps/workers/src/workflows/pipeline-dag.ts +210 -0
  269. package/apps/workers/src/workflows/pipeline-steps.ts +1393 -0
  270. package/apps/workers/tsconfig.json +16 -0
  271. package/apps/workers/vite.config.ts +35 -0
  272. package/docs/CHANGELOG.md +84 -0
  273. package/docs/agent-templates-and-runs.md +859 -0
  274. package/docs/aws-migration-plan.md +267 -0
  275. package/docs/impl-p0-form-builder-improvements.md +683 -0
  276. package/docs/on-prem-deployment-spec.docx +0 -0
  277. package/docs/on-prem-deployment-spec.md +378 -0
  278. package/docs/prd-form-builder-strategy.md +1120 -0
  279. package/docs/widget-ng-apf-packaging-spec.md +43 -0
  280. package/infra/k8s/charts/seadotdev/Chart.yaml +6 -0
  281. package/infra/k8s/charts/seadotdev/templates/_helpers.tpl +27 -0
  282. package/infra/k8s/charts/seadotdev/templates/api-v2.yaml +105 -0
  283. package/infra/k8s/charts/seadotdev/templates/external-secrets.yaml +83 -0
  284. package/infra/k8s/charts/seadotdev/templates/ingress.yaml +54 -0
  285. package/infra/k8s/charts/seadotdev/templates/main-app.yaml +104 -0
  286. package/infra/k8s/charts/seadotdev/templates/workers.yaml +182 -0
  287. package/infra/k8s/charts/seadotdev/values.yaml +143 -0
  288. package/infra/terraform/main.tf +399 -0
  289. package/libs/ai/.prettierignore +2 -0
  290. package/libs/ai/.prettierrc.js +5 -0
  291. package/libs/ai/README.md +139 -0
  292. package/libs/ai/eslint.config.mjs +3 -0
  293. package/libs/ai/package.json +42 -0
  294. package/libs/ai/src/index.ts +5 -0
  295. package/libs/ai/src/models.ts +19 -0
  296. package/libs/ai/src/rag/index.ts +1 -0
  297. package/libs/ai/src/rag/rag.test.ts +99 -0
  298. package/libs/ai/src/rag/rag.ts +510 -0
  299. package/libs/ai/tsconfig.json +21 -0
  300. package/libs/ai/vite.config.ts +38 -0
  301. package/libs/cache/.prettierignore +2 -0
  302. package/libs/cache/eslint.config.mjs +3 -0
  303. package/libs/cache/package.json +35 -0
  304. package/libs/cache/src/feedback.ts +77 -0
  305. package/libs/cache/src/index.ts +2 -0
  306. package/libs/cache/tsconfig.json +19 -0
  307. package/libs/cache/vite.config.ts +36 -0
  308. package/libs/clients/.prettierignore +6 -0
  309. package/libs/clients/eslint.config.mjs +3 -0
  310. package/libs/clients/package.json +59 -0
  311. package/libs/clients/src/azure.ts +249 -0
  312. package/libs/clients/src/gcp.ts +220 -0
  313. package/libs/clients/src/hatchet.ts +86 -0
  314. package/libs/clients/src/index.ts +8 -0
  315. package/libs/clients/src/loops.ts +86 -0
  316. package/libs/clients/src/polar.ts +77 -0
  317. package/libs/clients/src/posthog.ts +55 -0
  318. package/libs/clients/tsconfig.json +19 -0
  319. package/libs/clients/vite.config.ts +35 -0
  320. package/libs/config/.prettierignore +6 -0
  321. package/libs/config/.prettierrc.js +12 -0
  322. package/libs/config/eslint.config.mjs +3 -0
  323. package/libs/config/package.json +50 -0
  324. package/libs/config/src/azure.ts +54 -0
  325. package/libs/config/src/db.ts +18 -0
  326. package/libs/config/src/gcp.ts +53 -0
  327. package/libs/config/src/google.ts +17 -0
  328. package/libs/config/src/hatchet.ts +20 -0
  329. package/libs/config/src/index.ts +108 -0
  330. package/libs/config/src/llm.ts +17 -0
  331. package/libs/config/src/polar.ts +24 -0
  332. package/libs/config/src/util.ts +8 -0
  333. package/libs/config/src/vercel.ts +26 -0
  334. package/libs/config/tsconfig.json +19 -0
  335. package/libs/config/vite.config.ts +34 -0
  336. package/libs/core/.prettierignore +2 -0
  337. package/libs/core/eslint.config.mjs +3 -0
  338. package/libs/core/package.json +59 -0
  339. package/libs/core/src/chat/derived.ts +97 -0
  340. package/libs/core/src/chat/feedback.ts +293 -0
  341. package/libs/core/src/chat/index.ts +6 -0
  342. package/libs/core/src/chat/model.ts +92 -0
  343. package/libs/core/src/chat/prepare-tools.ts +286 -0
  344. package/libs/core/src/chat/prompts.ts +623 -0
  345. package/libs/core/src/chat/stream.ts +311 -0
  346. package/libs/core/src/chat/summarize.ts +168 -0
  347. package/libs/core/src/chat/tools/agent.ts +403 -0
  348. package/libs/core/src/chat/tools/chart-agent.ts +526 -0
  349. package/libs/core/src/chat/tools/chart-helpers/sandbox.ts +47 -0
  350. package/libs/core/src/chat/tools/chart.ts +86 -0
  351. package/libs/core/src/chat/tools/credit-agent.ts +1383 -0
  352. package/libs/core/src/chat/tools/credit.ts +1435 -0
  353. package/libs/core/src/chat/tools/deep-dive-agent.ts +100 -0
  354. package/libs/core/src/chat/tools/deep-dive.ts +141 -0
  355. package/libs/core/src/chat/tools/form.ts +449 -0
  356. package/libs/core/src/chat/tools/helpers.ts +91 -0
  357. package/libs/core/src/chat/tools/index.ts +42 -0
  358. package/libs/core/src/chat/tools/pipeline-artifact.ts +76 -0
  359. package/libs/core/src/chat/tools/report.ts +40 -0
  360. package/libs/core/src/chat/tools/search.ts +390 -0
  361. package/libs/core/src/chat/tools/submission.ts +227 -0
  362. package/libs/core/src/chat/tools/workflow.ts +684 -0
  363. package/libs/core/src/chat/types.ts +3 -0
  364. package/libs/core/src/data-extraction/classification/azure.ts +168 -0
  365. package/libs/core/src/data-extraction/classification/index.ts +1 -0
  366. package/libs/core/src/data-extraction/dal.ts +246 -0
  367. package/libs/core/src/data-extraction/form-structure-extractor.ts +294 -0
  368. package/libs/core/src/data-extraction/index.ts +4 -0
  369. package/libs/core/src/data-extraction/layout/azure.ts +730 -0
  370. package/libs/core/src/data-extraction/layout/excel.ts +180 -0
  371. package/libs/core/src/data-extraction/layout/gcp.ts +1071 -0
  372. package/libs/core/src/data-extraction/layout/index.ts +266 -0
  373. package/libs/core/src/data-extraction/layout/plaintext.ts +45 -0
  374. package/libs/core/src/data-extraction/models.ts +38 -0
  375. package/libs/core/src/data-extraction/pdf-utils.ts +96 -0
  376. package/libs/core/src/data-extraction/structuring/bank-statement.ts +1182 -0
  377. package/libs/core/src/data-extraction/structuring/custom.ts +495 -0
  378. package/libs/core/src/data-extraction/structuring/index.ts +290 -0
  379. package/libs/core/src/data-extraction/structuring/prompts.ts +69 -0
  380. package/libs/core/src/data-extraction/type-guards.ts +110 -0
  381. package/libs/core/src/data-extraction/types.ts +84 -0
  382. package/libs/core/src/data-extraction/utils.ts +31 -0
  383. package/libs/core/src/data-extraction/validation/bank-statement.ts +127 -0
  384. package/libs/core/src/deals.ts +17 -0
  385. package/libs/core/src/documents.ts +152 -0
  386. package/libs/core/src/index.ts +5 -0
  387. package/libs/core/src/pipelines/display.ts +678 -0
  388. package/libs/core/src/pipelines/execute.ts +2342 -0
  389. package/libs/core/src/pipelines/index.ts +4 -0
  390. package/libs/core/src/pipelines/list.ts +12 -0
  391. package/libs/core/src/pipelines/runs.ts +53 -0
  392. package/libs/core/tsconfig.json +20 -0
  393. package/libs/core/vite.config.ts +56 -0
  394. package/libs/dal/.prettierignore +6 -0
  395. package/libs/dal/.prettierrc.js +12 -0
  396. package/libs/dal/eslint.config.mjs +3 -0
  397. package/libs/dal/package.json +57 -0
  398. package/libs/dal/src/_tests/db.test.ts +19 -0
  399. package/libs/dal/src/_tests/mock-db.ts +60 -0
  400. package/libs/dal/src/api-key.test.ts +397 -0
  401. package/libs/dal/src/api-key.ts +110 -0
  402. package/libs/dal/src/billing.ts +23 -0
  403. package/libs/dal/src/conversation.test.ts +655 -0
  404. package/libs/dal/src/conversation.ts +532 -0
  405. package/libs/dal/src/deal.test.ts +45 -0
  406. package/libs/dal/src/deal.ts +87 -0
  407. package/libs/dal/src/defaults-consumer-lending-uk.ts +33 -0
  408. package/libs/dal/src/defaults-consumer-lending-us.ts +33 -0
  409. package/libs/dal/src/defaults-private-credit.ts +57 -0
  410. package/libs/dal/src/defaults-private-equity.ts +51 -0
  411. package/libs/dal/src/defaults-smb-lending-us.ts +1569 -0
  412. package/libs/dal/src/defaults-sme-lending-uk-express.ts +1527 -0
  413. package/libs/dal/src/defaults-sme-lending-uk.ts +1669 -0
  414. package/libs/dal/src/defaults-types.ts +23 -0
  415. package/libs/dal/src/defaults.ts +550 -0
  416. package/libs/dal/src/document.test.ts +70 -0
  417. package/libs/dal/src/document.ts +192 -0
  418. package/libs/dal/src/feedback.ts +255 -0
  419. package/libs/dal/src/form.test.ts +637 -0
  420. package/libs/dal/src/form.ts +1165 -0
  421. package/libs/dal/src/index.ts +20 -0
  422. package/libs/dal/src/invitation.test.ts +746 -0
  423. package/libs/dal/src/invitation.ts +207 -0
  424. package/libs/dal/src/member.test.ts +185 -0
  425. package/libs/dal/src/member.ts +80 -0
  426. package/libs/dal/src/organization.ts +116 -0
  427. package/libs/dal/src/permission.ts +25 -0
  428. package/libs/dal/src/pipeline.test.ts +388 -0
  429. package/libs/dal/src/pipeline.ts +4222 -0
  430. package/libs/dal/src/report.ts +199 -0
  431. package/libs/dal/src/result.ts +16 -0
  432. package/libs/dal/src/search.ts +172 -0
  433. package/libs/dal/src/session.test.ts +110 -0
  434. package/libs/dal/src/session.ts +31 -0
  435. package/libs/dal/src/submission.test.ts +1304 -0
  436. package/libs/dal/src/submission.ts +1396 -0
  437. package/libs/dal/src/tool.ts +159 -0
  438. package/libs/dal/src/user.ts +16 -0
  439. package/libs/dal/src/workflow.test.ts +89 -0
  440. package/libs/dal/src/workflow.ts +262 -0
  441. package/libs/dal/tsconfig.build.json +4 -0
  442. package/libs/dal/tsconfig.json +22 -0
  443. package/libs/dal/vite.config.ts +34 -0
  444. package/libs/db/.prettierignore +6 -0
  445. package/libs/db/.prettierrc.js +12 -0
  446. package/libs/db/eslint.config.mjs +3 -0
  447. package/libs/db/package.json +52 -0
  448. package/libs/db/src/index.ts +24 -0
  449. package/libs/db/src/relations.ts +549 -0
  450. package/libs/db/src/schema.ts +2 -0
  451. package/libs/db/src/schemas/api.ts +35 -0
  452. package/libs/db/src/schemas/conversations.ts +175 -0
  453. package/libs/db/src/schemas/core.ts +359 -0
  454. package/libs/db/src/schemas/documents.ts +181 -0
  455. package/libs/db/src/schemas/feedback.ts +40 -0
  456. package/libs/db/src/schemas/index.ts +26 -0
  457. package/libs/db/src/schemas/organisations.ts +97 -0
  458. package/libs/db/src/schemas/pipelines.ts +440 -0
  459. package/libs/db/src/schemas/users.ts +95 -0
  460. package/libs/db/src/types.ts +190 -0
  461. package/libs/db/src/utils.ts +14 -0
  462. package/libs/db/tsconfig.json +19 -0
  463. package/libs/db/vite.config.ts +31 -0
  464. package/libs/lint/.prettierignore +6 -0
  465. package/libs/lint/eslint.config.mjs +61 -0
  466. package/libs/lint/package.json +29 -0
  467. package/libs/lint/prettier.config.js +12 -0
  468. package/libs/schemas/.prettierignore +6 -0
  469. package/libs/schemas/.prettierrc.js +12 -0
  470. package/libs/schemas/README.md +15 -0
  471. package/libs/schemas/eslint.config.mjs +3 -0
  472. package/libs/schemas/package.json +67 -0
  473. package/libs/schemas/src/core/chat.ts +67 -0
  474. package/libs/schemas/src/core/core-result.ts +15 -0
  475. package/libs/schemas/src/core/data-extraction.ts +184 -0
  476. package/libs/schemas/src/core/layout.ts +478 -0
  477. package/libs/schemas/src/core/pipeline.ts +128 -0
  478. package/libs/schemas/src/core/submission.ts +97 -0
  479. package/libs/schemas/src/db/account.ts +57 -0
  480. package/libs/schemas/src/db/apiKey.ts +57 -0
  481. package/libs/schemas/src/db/context.ts +33 -0
  482. package/libs/schemas/src/db/conversation.ts +65 -0
  483. package/libs/schemas/src/db/deal.ts +42 -0
  484. package/libs/schemas/src/db/document.ts +103 -0
  485. package/libs/schemas/src/db/documentCitation.ts +58 -0
  486. package/libs/schemas/src/db/documentExtraction.ts +69 -0
  487. package/libs/schemas/src/db/fieldCorrection.ts +85 -0
  488. package/libs/schemas/src/db/form.ts +45 -0
  489. package/libs/schemas/src/db/formField.ts +59 -0
  490. package/libs/schemas/src/db/formGroup.ts +42 -0
  491. package/libs/schemas/src/db/impersonation.ts +39 -0
  492. package/libs/schemas/src/db/index.ts +25 -0
  493. package/libs/schemas/src/db/invitation.ts +42 -0
  494. package/libs/schemas/src/db/member.ts +36 -0
  495. package/libs/schemas/src/db/message.ts +58 -0
  496. package/libs/schemas/src/db/organization.ts +62 -0
  497. package/libs/schemas/src/db/session.ts +48 -0
  498. package/libs/schemas/src/db/submission.ts +54 -0
  499. package/libs/schemas/src/db/submissionGroup.ts +36 -0
  500. package/libs/schemas/src/db/submissionItem.ts +33 -0
  501. package/libs/schemas/src/db/submissionItemVersion.ts +70 -0
  502. package/libs/schemas/src/db/user.ts +51 -0
  503. package/libs/schemas/src/db/utils.ts +3 -0
  504. package/libs/schemas/src/db/verification.ts +36 -0
  505. package/libs/schemas/src/db/workflow.ts +42 -0
  506. package/libs/schemas/src/index.ts +10 -0
  507. package/libs/schemas/tsconfig.json +21 -0
  508. package/libs/schemas/vite.config.ts +38 -0
  509. package/libs/ui/.prettierignore +6 -0
  510. package/libs/ui/.prettierrc.js +12 -0
  511. package/libs/ui/components.json +24 -0
  512. package/libs/ui/eslint.config.mjs +3 -0
  513. package/libs/ui/package.json +142 -0
  514. package/libs/ui/src/components/chart-viz/chart.tsx +255 -0
  515. package/libs/ui/src/components/chart-viz/converters.ts +474 -0
  516. package/libs/ui/src/components/chart-viz/dashboard.tsx +146 -0
  517. package/libs/ui/src/components/chart-viz/index.ts +37 -0
  518. package/libs/ui/src/components/chart-viz/markdown.tsx +344 -0
  519. package/libs/ui/src/components/chart-viz/table.tsx +446 -0
  520. package/libs/ui/src/components/chart-viz/theme-context.tsx +70 -0
  521. package/libs/ui/src/components/chart-viz/themes/dark.ts +98 -0
  522. package/libs/ui/src/components/chart-viz/themes/index.ts +69 -0
  523. package/libs/ui/src/components/chart-viz/themes/light.ts +98 -0
  524. package/libs/ui/src/components/chart-viz/themes/tailwind.ts +326 -0
  525. package/libs/ui/src/components/chart-viz/themes/types.ts +99 -0
  526. package/libs/ui/src/components/chart-viz/tool-display.tsx +150 -0
  527. package/libs/ui/src/components/chart-viz/types.ts +95 -0
  528. package/libs/ui/src/components/doc-viewers/excel/index.tsx +431 -0
  529. package/libs/ui/src/components/doc-viewers/excel/themes.ts +160 -0
  530. package/libs/ui/src/components/doc-viewers/image/index.tsx +410 -0
  531. package/libs/ui/src/components/doc-viewers/pdf/index.tsx +258 -0
  532. package/libs/ui/src/components/doc-viewers/pdf/virtualized-pdf.tsx +556 -0
  533. package/libs/ui/src/components/misc/rel-date.tsx +52 -0
  534. package/libs/ui/src/components/misc/styled-link.tsx +2 -0
  535. package/libs/ui/src/components/table/data-table.tsx +546 -0
  536. package/libs/ui/src/components/table/report-table.tsx +305 -0
  537. package/libs/ui/src/components/table/sortable-column.tsx +34 -0
  538. package/libs/ui/src/components/ui/accordion.tsx +62 -0
  539. package/libs/ui/src/components/ui/alert-dialog.tsx +142 -0
  540. package/libs/ui/src/components/ui/alert.tsx +62 -0
  541. package/libs/ui/src/components/ui/artifact.tsx +118 -0
  542. package/libs/ui/src/components/ui/attachments.tsx +388 -0
  543. package/libs/ui/src/components/ui/avatar.tsx +39 -0
  544. package/libs/ui/src/components/ui/badge.tsx +43 -0
  545. package/libs/ui/src/components/ui/breadcrumb.tsx +102 -0
  546. package/libs/ui/src/components/ui/button-group.tsx +78 -0
  547. package/libs/ui/src/components/ui/button.tsx +79 -0
  548. package/libs/ui/src/components/ui/card.tsx +32 -0
  549. package/libs/ui/src/components/ui/carousel.tsx +228 -0
  550. package/libs/ui/src/components/ui/chain-of-thought.tsx +198 -0
  551. package/libs/ui/src/components/ui/checkbox.tsx +27 -0
  552. package/libs/ui/src/components/ui/citation.tsx +34 -0
  553. package/libs/ui/src/components/ui/code-block.tsx +500 -0
  554. package/libs/ui/src/components/ui/collapsible.tsx +19 -0
  555. package/libs/ui/src/components/ui/command.tsx +161 -0
  556. package/libs/ui/src/components/ui/conversation.tsx +90 -0
  557. package/libs/ui/src/components/ui/dialog.tsx +142 -0
  558. package/libs/ui/src/components/ui/dropdown-menu.tsx +246 -0
  559. package/libs/ui/src/components/ui/highlight.tsx +3 -0
  560. package/libs/ui/src/components/ui/hover-card.tsx +36 -0
  561. package/libs/ui/src/components/ui/inline-citation.tsx +251 -0
  562. package/libs/ui/src/components/ui/input-group.tsx +156 -0
  563. package/libs/ui/src/components/ui/input-otp.tsx +78 -0
  564. package/libs/ui/src/components/ui/input.tsx +21 -0
  565. package/libs/ui/src/components/ui/label.tsx +19 -0
  566. package/libs/ui/src/components/ui/model-selector.tsx +174 -0
  567. package/libs/ui/src/components/ui/multisidebar.tsx +750 -0
  568. package/libs/ui/src/components/ui/popover.tsx +43 -0
  569. package/libs/ui/src/components/ui/progress.tsx +28 -0
  570. package/libs/ui/src/components/ui/reasoning.tsx +178 -0
  571. package/libs/ui/src/components/ui/resizable.tsx +49 -0
  572. package/libs/ui/src/components/ui/scroll-area.tsx +54 -0
  573. package/libs/ui/src/components/ui/select.tsx +171 -0
  574. package/libs/ui/src/components/ui/separator.tsx +26 -0
  575. package/libs/ui/src/components/ui/sheet.tsx +128 -0
  576. package/libs/ui/src/components/ui/shimmer.tsx +53 -0
  577. package/libs/ui/src/components/ui/skeleton.tsx +13 -0
  578. package/libs/ui/src/components/ui/sonner.tsx +23 -0
  579. package/libs/ui/src/components/ui/switch.tsx +26 -0
  580. package/libs/ui/src/components/ui/table.tsx +96 -0
  581. package/libs/ui/src/components/ui/tabs.tsx +52 -0
  582. package/libs/ui/src/components/ui/textarea.tsx +41 -0
  583. package/libs/ui/src/components/ui/tool.tsx +209 -0
  584. package/libs/ui/src/components/ui/tooltip.tsx +58 -0
  585. package/libs/ui/src/components/ui/typography.tsx +113 -0
  586. package/libs/ui/src/fonts/manrope-v15-latin-300.woff2 +0 -0
  587. package/libs/ui/src/fonts/manrope-v15-latin-400.woff2 +0 -0
  588. package/libs/ui/src/fonts/manrope-v15-latin-500.woff2 +0 -0
  589. package/libs/ui/src/fonts/manrope-v15-latin-600.woff2 +0 -0
  590. package/libs/ui/src/hooks/use-mobile.ts +19 -0
  591. package/libs/ui/src/lib/utils.ts +6 -0
  592. package/libs/ui/src/styles/fonts.css +35 -0
  593. package/libs/ui/src/styles/style.css +218 -0
  594. package/libs/ui/tsconfig.json +21 -0
  595. package/libs/ui/vite.config.ts +80 -0
  596. package/libs/ui-lit/README.md +245 -0
  597. package/libs/ui-lit/TESTING_GUIDE.md +296 -0
  598. package/libs/ui-lit/eslint.config.mjs +3 -0
  599. package/libs/ui-lit/package.json +41 -0
  600. package/libs/ui-lit/scripts/build-css.js +43 -0
  601. package/libs/ui-lit/src/components/sea-alert.ts +132 -0
  602. package/libs/ui-lit/src/components/sea-button.ts +95 -0
  603. package/libs/ui-lit/src/components/sea-card.ts +113 -0
  604. package/libs/ui-lit/src/components/sea-input.ts +184 -0
  605. package/libs/ui-lit/src/components/sea-spinner.ts +65 -0
  606. package/libs/ui-lit/src/index.ts +15 -0
  607. package/libs/ui-lit/src/lib/utils.ts +6 -0
  608. package/libs/ui-lit/src/styles/tailwind.css +76 -0
  609. package/libs/ui-lit/src/theme.css +66 -0
  610. package/libs/ui-lit/src/theme.ts +79 -0
  611. package/libs/ui-lit/src/vite-env.d.ts +6 -0
  612. package/libs/ui-lit/tailwind.config.ts +50 -0
  613. package/libs/ui-lit/test.html +289 -0
  614. package/libs/ui-lit/tsconfig.json +23 -0
  615. package/libs/ui-lit/vite.config.ts +31 -0
  616. package/libs/ui-lit/vite.css.config.ts +20 -0
  617. package/libs/util/.prettierignore +6 -0
  618. package/libs/util/.prettierrc.js +12 -0
  619. package/libs/util/eslint.config.mjs +3 -0
  620. package/libs/util/package.json +45 -0
  621. package/libs/util/src/billing.ts +10 -0
  622. package/libs/util/src/data-transform.ts +19 -0
  623. package/libs/util/src/encryption.ts +45 -0
  624. package/libs/util/src/fmt.test.ts +9 -0
  625. package/libs/util/src/fmt.ts +71 -0
  626. package/libs/util/src/fuzzy.ts +47 -0
  627. package/libs/util/src/id.ts +24 -0
  628. package/libs/util/src/invariant.ts +31 -0
  629. package/libs/util/src/sub-name.ts +7 -0
  630. package/libs/util/tsconfig.json +19 -0
  631. package/libs/util/vite.config.ts +34 -0
  632. package/package.json +28 -0
  633. package/packages/widget/.prettierignore +6 -0
  634. package/packages/widget/.prettierrc.js +12 -0
  635. package/packages/widget/README.md +95 -0
  636. package/packages/widget/eslint.config.mjs +11 -0
  637. package/packages/widget/openapi-ts.config.ts +8 -0
  638. package/packages/widget/package.json +89 -0
  639. package/packages/widget/postcss.config.mjs +10 -0
  640. package/packages/widget/src/clients/api/client/client.ts +187 -0
  641. package/packages/widget/src/clients/api/client/index.ts +22 -0
  642. package/packages/widget/src/clients/api/client/types.ts +192 -0
  643. package/packages/widget/src/clients/api/client/utils.ts +394 -0
  644. package/packages/widget/src/clients/api/client.gen.ts +18 -0
  645. package/packages/widget/src/clients/api/core/auth.ts +39 -0
  646. package/packages/widget/src/clients/api/core/bodySerializer.ts +74 -0
  647. package/packages/widget/src/clients/api/core/params.ts +132 -0
  648. package/packages/widget/src/clients/api/core/pathSerializer.ts +169 -0
  649. package/packages/widget/src/clients/api/core/types.ts +80 -0
  650. package/packages/widget/src/clients/api/index.ts +3 -0
  651. package/packages/widget/src/clients/api/sdk.gen.ts +805 -0
  652. package/packages/widget/src/clients/api/types.gen.ts +2085 -0
  653. package/packages/widget/src/components/container.tsx +42 -0
  654. package/packages/widget/src/components/data-display.tsx +384 -0
  655. package/packages/widget/src/components/data-viewer.tsx +311 -0
  656. package/packages/widget/src/components/doc-list.tsx +102 -0
  657. package/packages/widget/src/components/field-correction-modal.tsx +265 -0
  658. package/packages/widget/src/components/header.tsx +71 -0
  659. package/packages/widget/src/components/new-submission.tsx +290 -0
  660. package/packages/widget/src/components/sidebar-right.tsx +19 -0
  661. package/packages/widget/src/components/submission-card.tsx +66 -0
  662. package/packages/widget/src/components/submission-page.tsx +75 -0
  663. package/packages/widget/src/components/upload-doc.tsx +241 -0
  664. package/packages/widget/src/components/widget.tsx +101 -0
  665. package/packages/widget/src/index.tsx +167 -0
  666. package/packages/widget/src/lib/config.ts +2 -0
  667. package/packages/widget/src/lib/util.ts +40 -0
  668. package/packages/widget/src/styles/index.css +5 -0
  669. package/packages/widget/src/styles/tw-properties.css +337 -0
  670. package/packages/widget/src/vite-env.d.ts +3 -0
  671. package/packages/widget/tsconfig.app.json +35 -0
  672. package/packages/widget/tsconfig.json +4 -0
  673. package/packages/widget/tsconfig.node.json +24 -0
  674. package/packages/widget/vite.config.ts +116 -0
  675. package/packages/widget-lit/BOTTLENECKS.md +250 -0
  676. package/packages/widget-lit/IMPLEMENTATION_SUMMARY.md +295 -0
  677. package/packages/widget-lit/README.md +232 -0
  678. package/packages/widget-lit/eslint.config.mjs +3 -0
  679. package/packages/widget-lit/package.json +52 -0
  680. package/packages/widget-lit/src/api-client.ts +230 -0
  681. package/packages/widget-lit/src/api-client.ts.backup +218 -0
  682. package/packages/widget-lit/src/components/sea-chat.ts +382 -0
  683. package/packages/widget-lit/src/components/sea-submission-viewer.ts +267 -0
  684. package/packages/widget-lit/src/components/sea-widget.ts +317 -0
  685. package/packages/widget-lit/src/index.ts +48 -0
  686. package/packages/widget-lit/src/react.ts +58 -0
  687. package/packages/widget-lit/src/style.css +47 -0
  688. package/packages/widget-lit/tsconfig.json +24 -0
  689. package/packages/widget-lit/vite.config.ts +29 -0
  690. package/packages/widget-ng/DEVELOPMENT.md +74 -0
  691. package/packages/widget-ng/README.md +657 -0
  692. package/packages/widget-ng/dev.sh +14 -0
  693. package/packages/widget-ng/eslint.config.mjs +24 -0
  694. package/packages/widget-ng/ng-package.json +9 -0
  695. package/packages/widget-ng/package.json +85 -0
  696. package/packages/widget-ng/src/index.ts +45 -0
  697. package/packages/widget-ng/src/lib/components/sea-chat.component.ts +737 -0
  698. package/packages/widget-ng/src/lib/components/sea-data-viewer.component.ts +2240 -0
  699. package/packages/widget-ng/src/lib/components/sea-deal-form-modal.component.ts +702 -0
  700. package/packages/widget-ng/src/lib/components/sea-document-list.component.ts +350 -0
  701. package/packages/widget-ng/src/lib/components/sea-feedback-modal.component.ts +461 -0
  702. package/packages/widget-ng/src/lib/components/sea-file-upload.component.ts +655 -0
  703. package/packages/widget-ng/src/lib/components/sea-model-selection-modal.component.ts +367 -0
  704. package/packages/widget-ng/src/lib/components/sea-new-submission-modal.component.ts +414 -0
  705. package/packages/widget-ng/src/lib/components/sea-pdf-viewer.component.ts +869 -0
  706. package/packages/widget-ng/src/lib/components/sea-submission-card.component.ts +251 -0
  707. package/packages/widget-ng/src/lib/components/sea-widget.component.ts +684 -0
  708. package/packages/widget-ng/src/lib/models/submission.model.ts +170 -0
  709. package/packages/widget-ng/src/lib/pipes/markdown.pipe.ts +57 -0
  710. package/packages/widget-ng/src/lib/services/api-client.service.ts +715 -0
  711. package/packages/widget-ng/src/lib/services/chat.service.ts +330 -0
  712. package/packages/widget-ng/src/lib/services/config.service.ts +107 -0
  713. package/packages/widget-ng/src/web-component.ts +56 -0
  714. package/packages/widget-ng/tsconfig.json +25 -0
  715. package/packages/widget-ng/tsconfig.lib.json +9 -0
  716. package/packages/widget-ng/vite.config.elements.ts +26 -0
  717. package/packages/widget-ng/vitest.config.ts +19 -0
  718. package/packages/widget-ng/vitest.setup.ts +13 -0
  719. package/pnpm-workspace.yaml +18 -0
  720. package/render.yaml +136 -0
  721. package/scripts/README.md +57 -0
  722. package/scripts/package.json +22 -0
  723. package/scripts/python/.python-version +1 -0
  724. package/scripts/python/README.md +3 -0
  725. package/scripts/python/export-org-data.py +693 -0
  726. package/scripts/python/pyproject.toml +29 -0
  727. package/scripts/python/requirements-dev.lock +36 -0
  728. package/scripts/python/requirements.lock +36 -0
  729. package/scripts/python/src/gen.py +297 -0
  730. package/scripts/python/test.py +34 -0
  731. package/scripts/src/fix-storage-provider-mismatch.ts +239 -0
  732. package/scripts/src/sync-render-yaml.ts +290 -0
  733. package/scripts/src/test-chat-stream.ts +300 -0
  734. package/scripts/src/test-reconciliation.ts +230 -0
  735. package/scripts/tsconfig.json +15 -0
  736. package/tests/angular-test-app/.vscode/extensions.json +4 -0
  737. package/tests/angular-test-app/.vscode/launch.json +13 -0
  738. package/tests/angular-test-app/.vscode/tasks.json +24 -0
  739. package/tests/angular-test-app/README.md +59 -0
  740. package/tests/angular-test-app/angular.json +111 -0
  741. package/tests/angular-test-app/clean-start.sh +14 -0
  742. package/tests/angular-test-app/package.json +36 -0
  743. package/tests/angular-test-app/public/favicon.ico +0 -0
  744. package/tests/angular-test-app/src/app/app.component.ts +220 -0
  745. package/tests/angular-test-app/src/app/app.config.ts +5 -0
  746. package/tests/angular-test-app/src/env.d.ts +13 -0
  747. package/tests/angular-test-app/src/index.html +13 -0
  748. package/tests/angular-test-app/src/main.ts +6 -0
  749. package/tests/angular-test-app/src/styles.css +8 -0
  750. package/tests/angular-test-app/tsconfig.app.json +15 -0
  751. package/tests/angular-test-app/tsconfig.json +27 -0
  752. package/tests/crm-viewer-app/API_INTEGRATION_SUMMARY.md +295 -0
  753. package/tests/crm-viewer-app/CURRENT_ASSETS_FIELDS.md +148 -0
  754. package/tests/crm-viewer-app/FIELD_ID_MAPPING.md +206 -0
  755. package/tests/crm-viewer-app/INTEGRATION_GUIDE.md +309 -0
  756. package/tests/crm-viewer-app/README.md +174 -0
  757. package/tests/crm-viewer-app/REAL_API_INTEGRATION.md +240 -0
  758. package/tests/crm-viewer-app/UPDATED_IMPLEMENTATION.md +279 -0
  759. package/tests/crm-viewer-app/angular.json +114 -0
  760. package/tests/crm-viewer-app/package.json +35 -0
  761. package/tests/crm-viewer-app/src/app/app.component.ts +534 -0
  762. package/tests/crm-viewer-app/src/app/citation.service.ts +316 -0
  763. package/tests/crm-viewer-app/src/env.d.ts +16 -0
  764. package/tests/crm-viewer-app/src/index.html +19 -0
  765. package/tests/crm-viewer-app/src/main.ts +7 -0
  766. package/tests/crm-viewer-app/src/styles.css +409 -0
  767. package/tests/crm-viewer-app/src/template.html +2678 -0
  768. package/tests/crm-viewer-app/tsconfig.app.json +15 -0
  769. package/tests/crm-viewer-app/tsconfig.json +27 -0
  770. package/tests/e2e/package.json +17 -0
  771. package/tests/e2e/playwright.config.ts +75 -0
  772. package/tests/e2e/tests/api/health.spec.ts +10 -0
  773. package/tests/e2e/tests/app/example.spec.ts +10 -0
  774. package/tests/widget-test-app/.prettierignore +6 -0
  775. package/tests/widget-test-app/README.md +48 -0
  776. package/tests/widget-test-app/index.html +12 -0
  777. package/tests/widget-test-app/package.json +24 -0
  778. package/tests/widget-test-app/src/App.css +192 -0
  779. package/tests/widget-test-app/src/App.tsx +80 -0
  780. package/tests/widget-test-app/src/main.tsx +9 -0
  781. package/tests/widget-test-app/src/vite-env.d.ts +4 -0
  782. package/tests/widget-test-app/tsconfig.json +25 -0
  783. package/tests/widget-test-app/tsconfig.node.json +11 -0
  784. package/tests/widget-test-app/vite.config.ts +14 -0
@@ -0,0 +1,1393 @@
1
+ import { getWorkerConfig } from "@/lib/config";
2
+ import { createLanguageModel } from "@sea/ai/models";
3
+ import { HatchetClientMgr } from "@sea/clients/hatchet";
4
+ import { createPipelineArtifact } from "@sea/core";
5
+ import { addAdditionalPropertiesToJsonSchema } from "@sea/core/data-extraction/structuring/custom";
6
+ import { getForm } from "@sea/dal/form";
7
+ import {
8
+ createPipelineRunStep,
9
+ getGroupForStepRun,
10
+ getParentStepRuns,
11
+ getParentStepRunsWithDependencies,
12
+ getPipelineStepById,
13
+ getStepDocuments,
14
+ getStepIntegrationConfig,
15
+ getSubmissionGroups,
16
+ logRequestCall,
17
+ resolveStepBlockersOnCompletion,
18
+ storePipelineOutputData,
19
+ updatePipelineRunStepStatus,
20
+ } from "@sea/dal/pipeline";
21
+ import type { DenormGroup, DenormSubmission, DenormTable } from "@sea/dal/submission";
22
+ import {
23
+ createSubmissionWithConversation,
24
+ getDenormSubmission,
25
+ getDenormSubmissions,
26
+ syncSubmissionToForm,
27
+ } from "@sea/dal/submission";
28
+ import { db, PIPELINE_RUN_STEP_STATUS, schema } from "@sea/db";
29
+ import type { FormGroupHydrated, FormWithGroups, Member } from "@sea/db/types";
30
+ import { invariant } from "@sea/util/invariant";
31
+ import type { LanguageModel } from "ai";
32
+ import { jsonSchema, Output, stepCountIs, ToolLoopAgent, zodSchema, type JSONSchema7 } from "ai";
33
+ import { and, eq, inArray } from "drizzle-orm";
34
+ import pLimit from "p-limit";
35
+ import * as z from "zod/v4";
36
+ import { extractDataUnified } from "./extraction";
37
+
38
+ const config = getWorkerConfig();
39
+ const hatchet = new HatchetClientMgr(config.hatchet).getHatchet();
40
+
41
+ // ============================================================================
42
+ // Input/Output Types
43
+ // ============================================================================
44
+
45
+ // Use type instead of interface to allow index signature
46
+ export type StepExecutionInput = {
47
+ memberId: string;
48
+ runId: string;
49
+ runStepId: string;
50
+ stepId: string;
51
+ [key: string]: string; // Index signature for JsonObject compatibility
52
+ };
53
+
54
+ export type StepExecutionOutput = {
55
+ status: string;
56
+ outputSubmissionId?: string;
57
+ error?: string;
58
+ [key: string]: string | undefined; // Index signature for JsonObject compatibility
59
+ };
60
+
61
+ // ============================================================================
62
+ // Template Step Workflow - Spawns Multiple Instances
63
+ // ============================================================================
64
+
65
+ export type TemplateStepInput = StepExecutionInput & {
66
+ stepRole: "extraction" | "integration" | "analysis" | "manual";
67
+ };
68
+
69
+ export const templateStepWorkflow = hatchet.workflow<TemplateStepInput>({
70
+ name: "template-step",
71
+ });
72
+
73
+ // ============================================================================
74
+ // Helper Functions
75
+ // ============================================================================
76
+
77
+ function serializeGroup(group: DenormGroup): string {
78
+ const htmlParts: string[] = [];
79
+ htmlParts.push(`<h2>${group.name}</h2>`);
80
+ htmlParts.push("<dl>");
81
+
82
+ for (const item of group.items) {
83
+ htmlParts.push(`<dt>${item.name}</dt>`);
84
+ htmlParts.push(`<dd id="${item.id}">${String(item.value ?? "")}</dd>`);
85
+ }
86
+ for (const derived of group.derived) {
87
+ htmlParts.push(`<dt>${derived.name} (derived)</dt>`);
88
+ htmlParts.push(`<dd id="${derived.id}">${String(derived.value ?? "")}</dd>`);
89
+ }
90
+ htmlParts.push("</dl>");
91
+
92
+ return htmlParts.join("\n");
93
+ }
94
+
95
+ function serializeTable(table: DenormTable): string {
96
+ const htmlParts: string[] = [];
97
+
98
+ htmlParts.push(`<h2>${table.name}</h2>`);
99
+ htmlParts.push("<table>");
100
+
101
+ // Table header
102
+ htmlParts.push("<thead><tr>");
103
+ for (const col of table.columns) {
104
+ htmlParts.push(`<th>${col}</th>`);
105
+ }
106
+ htmlParts.push("</tr></thead>");
107
+
108
+ // Table body
109
+ htmlParts.push("<tbody>");
110
+ for (const row of table.rows) {
111
+ htmlParts.push("<tr>");
112
+
113
+ // Regular items
114
+ for (const item of row.items) {
115
+ htmlParts.push(`<td id="${item.id}">${String(item.value ?? "")}</td>`);
116
+ }
117
+
118
+ // Derived items
119
+ for (const derived of row.derived) {
120
+ htmlParts.push(`<td id="${derived.id}">${String(derived.value ?? "")}</td>`);
121
+ }
122
+
123
+ htmlParts.push("</tr>");
124
+ }
125
+ htmlParts.push("</tbody>");
126
+ htmlParts.push("</table>");
127
+
128
+ return htmlParts.join("\n");
129
+ }
130
+
131
+ /**
132
+ * Serialize submission to HTML for LLM consumption
133
+ */
134
+ function serializeSubmission(submission: DenormSubmission): string {
135
+ const htmlParts: string[] = [];
136
+
137
+ // Add submission header
138
+ htmlParts.push(`<section>`);
139
+ htmlParts.push(`<h1>${submission.formName}</h1>`);
140
+ if (submission.name) {
141
+ htmlParts.push(`<p><strong>Submission:</strong> ${submission.name}</p>`);
142
+ }
143
+
144
+ // Serialize single groups (definition lists)
145
+ for (const group of submission.groups) {
146
+ htmlParts.push(serializeGroup(group));
147
+ }
148
+
149
+ // Serialize tables (multi groups)
150
+ for (const table of submission.tables) {
151
+ htmlParts.push(serializeTable(table));
152
+ }
153
+ htmlParts.push("</section>");
154
+
155
+ return htmlParts.join("\n");
156
+ }
157
+
158
+ /**
159
+ * Build extraction schema for a group with reasoning field for pipeline analysis
160
+ */
161
+ function buildAnalysisSchemaFromGroup(
162
+ group: FormGroupHydrated,
163
+ ): z.ZodObject<Record<string, z.ZodType>> {
164
+ const groupFields: Record<string, z.ZodType> = {};
165
+
166
+ for (const field of group.fields) {
167
+ switch (field.type) {
168
+ case "string":
169
+ case "string-long":
170
+ groupFields[field.name] = z
171
+ .object({
172
+ value: z.string(),
173
+ refId: z.string(),
174
+ reasoning: z
175
+ .string()
176
+ .describe("Explanation of how this value was derived from the input data"),
177
+ })
178
+ .nullable()
179
+ .describe(field.hint);
180
+ break;
181
+ case "number":
182
+ case "money":
183
+ groupFields[field.name] = z
184
+ .object({
185
+ value: z.number(),
186
+ refId: z.string(),
187
+ reasoning: z
188
+ .string()
189
+ .describe("Explanation of how this value was derived from the input data"),
190
+ })
191
+ .nullable()
192
+ .describe(field.hint);
193
+ break;
194
+ case "boolean":
195
+ groupFields[field.name] = z
196
+ .object({
197
+ value: z.boolean(),
198
+ refId: z.string(),
199
+ reasoning: z
200
+ .string()
201
+ .describe("Explanation of how this value was derived from the input data"),
202
+ })
203
+ .nullable()
204
+ .describe(field.hint);
205
+ break;
206
+ case "date":
207
+ groupFields[field.name] = z
208
+ .object({
209
+ value: z.iso.date(),
210
+ refId: z.string(),
211
+ reasoning: z
212
+ .string()
213
+ .describe("Explanation of how this value was derived from the input data"),
214
+ })
215
+ .nullable()
216
+ .describe(field.hint);
217
+ break;
218
+ case "email":
219
+ groupFields[field.name] = z
220
+ .object({
221
+ value: z.email(),
222
+ refId: z.string(),
223
+ reasoning: z
224
+ .string()
225
+ .describe("Explanation of how this value was derived from the input data"),
226
+ })
227
+ .nullable()
228
+ .describe(field.hint);
229
+ break;
230
+ case "url":
231
+ groupFields[field.name] = z
232
+ .object({
233
+ value: z.string().describe("Valid URL"),
234
+ refId: z.string(),
235
+ reasoning: z
236
+ .string()
237
+ .describe("Explanation of how this value was derived from the input data"),
238
+ })
239
+ .nullable()
240
+ .describe(field.hint);
241
+ break;
242
+ case "enum":
243
+ if (field.options && field.options.length > 0) {
244
+ groupFields[field.name] = z
245
+ .object({
246
+ value: z.enum(field.options as [string, ...string[]]),
247
+ refId: z.string(),
248
+ reasoning: z
249
+ .string()
250
+ .describe("Explanation of how this value was derived from the input data"),
251
+ })
252
+ .nullable()
253
+ .describe(`${field.hint}. Must be one of: ${field.options.join(", ")}`);
254
+ } else {
255
+ groupFields[field.name] = z
256
+ .object({
257
+ value: z.string(),
258
+ refId: z.string(),
259
+ reasoning: z
260
+ .string()
261
+ .describe("Explanation of how this value was derived from the input data"),
262
+ })
263
+ .nullable()
264
+ .describe(field.hint);
265
+ }
266
+ break;
267
+ default:
268
+ groupFields[field.name] = z
269
+ .object({
270
+ value: z.unknown(),
271
+ refId: z.string(),
272
+ reasoning: z
273
+ .string()
274
+ .describe("Explanation of how this value was derived from the input data"),
275
+ })
276
+ .nullable()
277
+ .describe(field.hint);
278
+ break;
279
+ }
280
+ }
281
+
282
+ return group.multi
283
+ ? z.object({
284
+ [group.name]: z.array(z.object(groupFields)),
285
+ })
286
+ : z.object({
287
+ [group.name]: z.object(groupFields),
288
+ });
289
+ }
290
+
291
+ /**
292
+ * Build response schema from output form groups for pipeline analysis
293
+ */
294
+ function buildStepResponseSchema(outputFormGroups: FormGroupHydrated[]) {
295
+ const extractionSchema = outputFormGroups.reduce((acc, group) => {
296
+ const groupSchema = buildAnalysisSchemaFromGroup(group);
297
+ return z.object({
298
+ ...acc.shape,
299
+ ...groupSchema.shape,
300
+ });
301
+ }, z.object({}));
302
+
303
+ return z.object({
304
+ reasoning: z.string().nullable(),
305
+ data: extractionSchema.nullable(),
306
+ });
307
+ }
308
+
309
+ /**
310
+ * Build HTTP request from integration config template
311
+ */
312
+ async function buildHttpRequest({
313
+ config: reqConfig,
314
+ parentData,
315
+ }: {
316
+ config: {
317
+ method: "GET" | "POST" | "PUT" | "DELETE";
318
+ urlTemplate: string;
319
+ headers: Record<string, string>;
320
+ bodyTemplate?: string;
321
+ };
322
+ parentData: DenormSubmission[];
323
+ }): Promise<{
324
+ method: string;
325
+ url: string;
326
+ headers: Record<string, string>;
327
+ body?: string;
328
+ }> {
329
+ // Build variable map from parent submissions
330
+ const variables = new Map<string, string>();
331
+
332
+ for (const submission of parentData) {
333
+ // Add form-level variables
334
+ variables.set(`form.name`, submission.formName);
335
+
336
+ // Add field-level variables from groups
337
+ for (const group of submission.groups) {
338
+ for (const item of group.items) {
339
+ const key = `${group.name}.${item.name}`;
340
+ const value = String(item.value ?? "");
341
+ variables.set(key, value);
342
+ }
343
+
344
+ for (const derived of group.derived) {
345
+ const key = `${group.name}.${derived.name}`;
346
+ const value = String(derived.value ?? "");
347
+ variables.set(key, value);
348
+ }
349
+ }
350
+
351
+ // Add table row variables (use first row)
352
+ for (const table of submission.tables) {
353
+ const firstRow = table.rows[0];
354
+ if (firstRow) {
355
+ for (const item of firstRow.items) {
356
+ const key = `${table.name}.${item.name}`;
357
+ const value = String(item.value ?? "");
358
+ variables.set(key, value);
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+ // Substitute variables in templates
365
+ const substituteVariables = (template: string): string => {
366
+ return template.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
367
+ const trimmedName = varName.trim();
368
+ const value = variables.get(trimmedName);
369
+
370
+ if (value !== undefined) {
371
+ return encodeURIComponent(value);
372
+ }
373
+
374
+ console.warn(`[buildHttpRequest] Variable not found: ${trimmedName}`);
375
+ return match;
376
+ });
377
+ };
378
+
379
+ const url = substituteVariables(reqConfig.urlTemplate);
380
+
381
+ const headers: Record<string, string> = {};
382
+ for (const [key, value] of Object.entries(reqConfig.headers)) {
383
+ headers[key] = substituteVariables(value);
384
+ }
385
+
386
+ const body = reqConfig.bodyTemplate ? substituteVariables(reqConfig.bodyTemplate) : undefined;
387
+
388
+ return {
389
+ method: reqConfig.method,
390
+ url,
391
+ headers,
392
+ body,
393
+ };
394
+ }
395
+
396
+ // ============================================================================
397
+ // LLM Analysis Helper
398
+ // ============================================================================
399
+
400
+ async function runAnalysisWithLLM({
401
+ member,
402
+ runId,
403
+ runStepId,
404
+ step,
405
+ inputSubmissions,
406
+ outputForm,
407
+ spawningGroup,
408
+ model,
409
+ }: {
410
+ member: Member;
411
+ runId: string;
412
+ runStepId: string;
413
+ step: {
414
+ id: string;
415
+ description: string;
416
+ prompt: string;
417
+ toolsAllowed: string[] | null;
418
+ };
419
+ inputSubmissions: DenormSubmission[];
420
+ outputForm: FormWithGroups;
421
+ spawningGroup?: DenormGroup | null;
422
+ model: LanguageModel;
423
+ }) {
424
+ try {
425
+ // Build output schema
426
+ const workflowStepResponseSchema = buildStepResponseSchema(outputForm.groups);
427
+ const strictSchema = zodSchema(workflowStepResponseSchema);
428
+ addAdditionalPropertiesToJsonSchema(strictSchema.jsonSchema as JSONSchema7);
429
+
430
+ // Build instructions
431
+ const instructionsParts = [
432
+ `
433
+ <role>You are a precise data transformation specialist executing one step in a data workflow.</role>
434
+
435
+ <task>
436
+ - Your broad task is ${step.description}.
437
+ - The user will specify the exact instructions on how to perform the data transformations for this step in the <step_instructions> section.
438
+ </task>
439
+
440
+ <input_format>
441
+ - HTML-formatted submission data with multiple sections
442
+ - Each field has an id attribute for reference (e.g., id="field-123")
443
+ - Sections may include definition lists (<dl>) and tables (<table>)
444
+ - Multiple input submissions may be provided
445
+ </input_format>
446
+
447
+ <transformation_rules>
448
+ 1. <completeness>Extract ALL fields defined in the output schema</completeness>
449
+ 2. <output_format>For each primitive field (string, number, boolean), output:
450
+ "fieldName": { "value": <transformed_value>, "refId": "<element_id>", "reasoning": "<explanation>" }</output_format>
451
+ 3. <multiple_references>When a value is derived from multiple input elements, list all element IDs separated by commas in the refId field</multiple_references>
452
+ 4. <reasoning_requirement>
453
+ - The reasoning field MUST explain HOW the value was derived from the input data.
454
+ - When referring to specific elements from input data, refer to them by the corresponding header trace under which they reside
455
+ </reasoning_requirement>
456
+ 5. <reasoning_examples>
457
+ - "Calculated by summing TransactionAmount fields from rows 1-5"
458
+ - "Extracted from BankName field in section 'Bank Statement'"
459
+ - "Average of Balance values across all input data"
460
+ - "Converted from USD to GBP using exchange rate in row 3"</reasoning_examples>
461
+ 6. <source_fidelity>ONLY use values present in or reasonably inferred from the input data - NO external knowledge</source_fidelity>
462
+ 7. <reference_requirement>EVERY extracted value MUST include a refId pointing to the source element(s) and a reasoning explaining the transformation</reference_requirement>
463
+ </transformation_rules>
464
+
465
+ <output_requirements>
466
+ - Return a JSON object conforming to the provided schema
467
+ - Validate output matches schema structure exactly
468
+ - All required fields must be present
469
+ - All values must include refId and reasoning
470
+ </output_requirements>`,
471
+ ];
472
+
473
+ instructionsParts.push("<step_instructions>", step.prompt, "</step_instructions>");
474
+ const instructions = instructionsParts.join("\n");
475
+
476
+ // Build messages
477
+ const serializedInput = inputSubmissions.map((sub) => serializeSubmission(sub));
478
+ const messages = [
479
+ {
480
+ role: "user" as const,
481
+ content: `===== INPUT DATA =====\n${serializedInput}`,
482
+ },
483
+ ];
484
+ if (spawningGroup) {
485
+ messages.push({
486
+ role: "user" as const,
487
+ content: ["<main_input>", serializeGroup(spawningGroup), "</main_input>"].join("\n"),
488
+ });
489
+ }
490
+
491
+ // Load pipeline-specific tools
492
+ const tools = {
493
+ createArtifact: createPipelineArtifact({
494
+ member,
495
+ runId,
496
+ runStepId,
497
+ }),
498
+ };
499
+
500
+ // Create agent with structured output
501
+ const agent = new ToolLoopAgent({
502
+ model,
503
+ instructions,
504
+ tools,
505
+ stopWhen: stepCountIs(10),
506
+ output: Output.object({
507
+ schema: jsonSchema(strictSchema.jsonSchema),
508
+ }),
509
+ });
510
+
511
+ const result = await agent.generate({ messages });
512
+ const parsedOutput = workflowStepResponseSchema.parse(result.output);
513
+
514
+ return {
515
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
516
+ data: parsedOutput.data,
517
+ };
518
+ } catch (error) {
519
+ return {
520
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
521
+ data: null,
522
+ error: error instanceof Error ? error.message : "Analysis failed",
523
+ };
524
+ }
525
+ }
526
+
527
+ // ============================================================================
528
+ // Extraction Step Task
529
+ // ============================================================================
530
+
531
+ export const executeExtractionStepTask = hatchet.task<StepExecutionInput, StepExecutionOutput>({
532
+ name: "execute-extraction-step",
533
+ timeout: "30m", // Extraction can take a while
534
+ fn: async (input) => {
535
+ console.log("[executeExtractionStepTask] Starting...");
536
+ const { memberId, runStepId, stepId } = input;
537
+
538
+ try {
539
+ // Get member
540
+ const member = await db.query.member.findFirst({
541
+ where: eq(schema.member.id, memberId),
542
+ });
543
+ invariant(member, "Member not found");
544
+
545
+ // Get run step
546
+ const runStep = await db.query.pipelineRunStep.findFirst({
547
+ where: eq(schema.pipelineRunStep.id, runStepId),
548
+ });
549
+ invariant(runStep, "Run step not found");
550
+
551
+ // Get step definition
552
+ const stepResult = await getPipelineStepById({ member, stepId });
553
+ if (!stepResult.ok) {
554
+ throw new Error(`Step ${stepId} not found`);
555
+ }
556
+ const step = stepResult.data;
557
+
558
+ await updatePipelineRunStepStatus({
559
+ member,
560
+ runStepId,
561
+ status: PIPELINE_RUN_STEP_STATUS.RUNNING,
562
+ });
563
+
564
+ // Get documents linked to this step run
565
+ const documentsResult = await getStepDocuments({
566
+ member,
567
+ runStepId,
568
+ });
569
+
570
+ if (!documentsResult.ok) {
571
+ throw new Error("Failed to load step documents");
572
+ }
573
+
574
+ if (documentsResult.data.length === 0) {
575
+ throw new Error("No documents linked to extraction step");
576
+ }
577
+
578
+ // Validate we have output forms
579
+ if (step.outputForms.length === 0) {
580
+ throw new Error("Extraction step missing output form");
581
+ }
582
+
583
+ // Get pipeline run to access dealId
584
+ const pipelineRun = await db.query.pipelineRun.findFirst({
585
+ where: eq(schema.pipelineRun.id, runStep.runId),
586
+ });
587
+ if (!pipelineRun) {
588
+ throw new Error("Pipeline run not found");
589
+ }
590
+
591
+ // Process each output form
592
+ const outputSubmissionIds: string[] = [];
593
+
594
+ // Fetch all form names upfront
595
+ const formIds = step.outputForms.map((f) => f.formId);
596
+ const forms = await db.query.form.findMany({
597
+ where: (fields, { inArray }) => inArray(fields.id, formIds),
598
+ });
599
+ const formIdToName = new Map(forms.map((f) => [f.id, f.name]));
600
+
601
+ for (const [formIndex, outputFormConfig] of step.outputForms.entries()) {
602
+ const outputFormId = outputFormConfig.formId;
603
+ const formName = formIdToName.get(outputFormId);
604
+
605
+ console.log(
606
+ `[executeExtractionStepTask] Processing output form ${formIndex + 1}/${step.outputForms.length}: ${outputFormId} (${formName})`,
607
+ );
608
+
609
+ // Build submission name
610
+ let submissionName: string;
611
+ if (runStep.spawnType === "instance") {
612
+ if (step.outputForms.length > 1) {
613
+ submissionName = `${step.name} - Instance ${runStep.stepRunIndex! + 1} - ${formName ?? `Form ${formIndex + 1}`}`;
614
+ } else {
615
+ submissionName = `${step.name} - Instance ${runStep.stepRunIndex! + 1}`;
616
+ }
617
+ } else {
618
+ if (step.outputForms.length > 1) {
619
+ submissionName = `${step.name} - ${formName ?? `Form ${formIndex + 1}`}`;
620
+ } else {
621
+ submissionName = `${step.name} output`;
622
+ }
623
+ }
624
+
625
+ // Create output submission for extracted data
626
+ const outputSubmission = await createSubmissionWithConversation({
627
+ member,
628
+ data: {
629
+ formId: outputFormId,
630
+ dealId: pipelineRun.dealId,
631
+ name: submissionName,
632
+ status: "draft",
633
+ type: "extraction",
634
+ },
635
+ });
636
+
637
+ await syncSubmissionToForm({
638
+ member,
639
+ submissionId: outputSubmission.id,
640
+ });
641
+
642
+ // For each document, create documentExtraction and trigger extraction workflow directly
643
+ const extractionPromises = documentsResult.data.map(async (document) => {
644
+ // Create documentExtraction record
645
+ const [documentExtraction] = await db
646
+ .insert(schema.documentExtraction)
647
+ .values({
648
+ documentId: document.id,
649
+ submissionId: outputSubmission.id,
650
+ status: "pending",
651
+ extractionModel: "smart",
652
+ extractionTrigger: "api",
653
+ })
654
+ .returning({ id: schema.documentExtraction.id });
655
+
656
+ invariant(
657
+ documentExtraction,
658
+ `Failed to create documentExtraction for document ${document.id}`,
659
+ );
660
+
661
+ console.log(
662
+ `[executeExtractionStepTask] Calling extraction workflow for form ${formIndex + 1}, document: ${document.name} (extractionId: ${documentExtraction.id})`,
663
+ );
664
+
665
+ // Call extraction workflow directly (no event, no polling!)
666
+ await extractDataUnified.run({
667
+ documentExtractionId: documentExtraction.id,
668
+ options: {
669
+ extractionModel: "general",
670
+ reasoningEffort: "medium",
671
+ },
672
+ userPrompt: step.prompt || undefined,
673
+ });
674
+
675
+ console.log(
676
+ `[executeExtractionStepTask] Extraction completed for form ${formIndex + 1}, document: ${document.name}`,
677
+ );
678
+
679
+ return documentExtraction.id;
680
+ });
681
+
682
+ // Wait for all extractions to complete for this form
683
+ await Promise.all(extractionPromises);
684
+
685
+ // Link output submission to run step
686
+ await db.insert(schema.pipelineRunStepOutputSubmission).values({
687
+ runStepId,
688
+ submissionId: outputSubmission.id,
689
+ });
690
+
691
+ outputSubmissionIds.push(outputSubmission.id);
692
+ }
693
+
694
+ // Mark step as completed
695
+ await updatePipelineRunStepStatus({
696
+ member,
697
+ runStepId,
698
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
699
+ });
700
+
701
+ // Resolve blockers now that extraction is complete
702
+ await resolveStepBlockersOnCompletion({
703
+ member,
704
+ runStepId,
705
+ });
706
+
707
+ console.log(
708
+ `[executeExtractionStepTask] Completed extraction step with ${documentsResult.data.length} document(s) across ${step.outputForms.length} form(s), output submissions: ${outputSubmissionIds.join(", ")}`,
709
+ );
710
+
711
+ return {
712
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
713
+ outputSubmissionId: outputSubmissionIds[0], // Keep first for backwards compatibility
714
+ };
715
+ } catch (error) {
716
+ console.error("[executeExtractionStepTask] Error:", error);
717
+ await updatePipelineRunStepStatus({
718
+ member: { id: memberId } as Member,
719
+ runStepId,
720
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
721
+ error: error instanceof Error ? error.message : "Unknown error",
722
+ });
723
+
724
+ return {
725
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
726
+ error: error instanceof Error ? error.message : "Extraction step failed",
727
+ };
728
+ }
729
+ },
730
+ });
731
+
732
+ // ============================================================================
733
+ // Integration Step Task
734
+ // ============================================================================
735
+
736
+ export const executeIntegrationStepTask = hatchet.task<StepExecutionInput, StepExecutionOutput>({
737
+ name: "execute-integration-step",
738
+ timeout: "10m",
739
+ fn: async (input) => {
740
+ const { memberId, runStepId, stepId } = input;
741
+
742
+ try {
743
+ const member = await db.query.member.findFirst({
744
+ where: eq(schema.member.id, memberId),
745
+ });
746
+ invariant(member, "Member not found");
747
+
748
+ const runStep = await db.query.pipelineRunStep.findFirst({
749
+ where: eq(schema.pipelineRunStep.id, runStepId),
750
+ });
751
+ invariant(runStep, "Run step not found");
752
+
753
+ const stepResult = await getPipelineStepById({ member, stepId });
754
+ if (!stepResult.ok) {
755
+ throw new Error(`Step ${stepId} not found`);
756
+ }
757
+ const step = stepResult.data;
758
+
759
+ await updatePipelineRunStepStatus({
760
+ member,
761
+ runStepId,
762
+ status: PIPELINE_RUN_STEP_STATUS.RUNNING,
763
+ });
764
+
765
+ // Get integration config
766
+ const integrationConfigResult = await getStepIntegrationConfig({
767
+ member,
768
+ stepId,
769
+ });
770
+
771
+ if (!integrationConfigResult.ok || !integrationConfigResult.data) {
772
+ throw new Error("Integration step missing config");
773
+ }
774
+
775
+ const integrationConfig = integrationConfigResult.data;
776
+
777
+ // Get parent step outputs
778
+ const parentStepRunsResult = await getParentStepRuns({
779
+ member,
780
+ runStepId,
781
+ });
782
+
783
+ if (!parentStepRunsResult.ok) {
784
+ throw new Error("Failed to load parent step outputs");
785
+ }
786
+
787
+ const parentStepRuns = parentStepRunsResult.data;
788
+
789
+ // Load output submissions for each parent step run
790
+ const parentSubmissions = await Promise.all(
791
+ parentStepRuns.map(async (p) => {
792
+ const outputMapping = await db.query.pipelineRunStepOutputSubmission.findFirst({
793
+ where: eq(schema.pipelineRunStepOutputSubmission.runStepId, p.id),
794
+ });
795
+ if (!outputMapping) return null;
796
+ return getDenormSubmission({
797
+ member,
798
+ submissionId: outputMapping.submissionId,
799
+ withCitations: true,
800
+ withTransformations: true,
801
+ });
802
+ }),
803
+ );
804
+
805
+ const validParentSubmissions = parentSubmissions.filter(
806
+ (s): s is NonNullable<typeof s> => s !== null,
807
+ );
808
+
809
+ // Build request from template
810
+ const request = await buildHttpRequest({
811
+ config: {
812
+ method: integrationConfig.method as "GET" | "POST" | "PUT" | "DELETE",
813
+ urlTemplate: integrationConfig.urlTemplate,
814
+ headers: integrationConfig.headers,
815
+ bodyTemplate: integrationConfig.bodyTemplate ?? undefined,
816
+ },
817
+ parentData: validParentSubmissions,
818
+ });
819
+
820
+ // Make API call
821
+ const startTime = Date.now();
822
+ let statusCode: number | undefined;
823
+ let responseBody: unknown;
824
+ let error: string | undefined;
825
+
826
+ try {
827
+ const response = await fetch(request.url, {
828
+ method: request.method,
829
+ headers: request.headers,
830
+ body: request.body,
831
+ });
832
+
833
+ statusCode = response.status;
834
+ responseBody = await response.json();
835
+ } catch (err) {
836
+ error = err instanceof Error ? err.message : "Request failed";
837
+ }
838
+
839
+ const durationMs = Date.now() - startTime;
840
+
841
+ // Log request call
842
+ await logRequestCall({
843
+ member,
844
+ runStepId,
845
+ method: request.method,
846
+ url: request.url,
847
+ requestHeaders: request.headers,
848
+ requestBody: request.body,
849
+ statusCode,
850
+ responseBody,
851
+ durationMs,
852
+ error,
853
+ });
854
+
855
+ if (error || !statusCode || statusCode >= 400) {
856
+ throw new Error(error || `HTTP ${statusCode}`);
857
+ }
858
+
859
+ await updatePipelineRunStepStatus({
860
+ member,
861
+ runStepId,
862
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
863
+ });
864
+
865
+ // Resolve blockers now that integration is complete
866
+ await resolveStepBlockersOnCompletion({
867
+ member,
868
+ runStepId,
869
+ });
870
+
871
+ return {
872
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
873
+ };
874
+ } catch (error) {
875
+ await updatePipelineRunStepStatus({
876
+ member: { id: memberId } as Member,
877
+ runStepId,
878
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
879
+ error: error instanceof Error ? error.message : "Integration step failed",
880
+ });
881
+
882
+ return {
883
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
884
+ error: error instanceof Error ? error.message : "Integration step failed",
885
+ };
886
+ }
887
+ },
888
+ });
889
+
890
+ // ============================================================================
891
+ // Analysis Step Task
892
+ // ============================================================================
893
+
894
+ export const executeAnalysisStepTask = hatchet.task<StepExecutionInput, StepExecutionOutput>({
895
+ name: "execute-analysis-step",
896
+ timeout: "20m", // Analysis with LLM can take time
897
+ fn: async (input) => {
898
+ const { memberId, runStepId } = input;
899
+
900
+ try {
901
+ const member = await db.query.member.findFirst({
902
+ where: eq(schema.member.id, memberId),
903
+ });
904
+ invariant(member, "Member not found");
905
+
906
+ const runStep = await db.query.pipelineRunStep.findFirst({
907
+ with: { step: { with: { outputForms: true } }, run: true },
908
+ where: eq(schema.pipelineRunStep.id, runStepId),
909
+ });
910
+ invariant(runStep, "Run step not found");
911
+
912
+ await updatePipelineRunStepStatus({
913
+ member,
914
+ runStepId,
915
+ status: PIPELINE_RUN_STEP_STATUS.RUNNING,
916
+ });
917
+
918
+ // Get parent step runs with dependency configurations
919
+ const parentStepRunsResult = await getParentStepRunsWithDependencies({
920
+ member,
921
+ runStepId,
922
+ });
923
+
924
+ if (!parentStepRunsResult.ok) {
925
+ throw new Error("Failed to load parent step runs");
926
+ }
927
+ const parentStepRuns = parentStepRunsResult.data;
928
+
929
+ // Load output submissions for each parent step run
930
+ const parentSubmissionIds = (
931
+ await db
932
+ .select()
933
+ .from(schema.pipelineRunStepOutputSubmission)
934
+ .where(
935
+ inArray(
936
+ schema.pipelineRunStepOutputSubmission.runStepId,
937
+ parentStepRuns.map((p) => p.id),
938
+ ),
939
+ )
940
+ ).map((row) => row.submissionId);
941
+ const parentSubmissions = await getDenormSubmissions({
942
+ member,
943
+ submissionIds: parentSubmissionIds,
944
+ withCitations: true,
945
+ withTransformations: true,
946
+ });
947
+
948
+ // Check if this is a multi step - if so filter input submissions accordingly
949
+ const multiGroupResult = await getGroupForStepRun({
950
+ member,
951
+ runStepId,
952
+ });
953
+ const spawningGroup = multiGroupResult.ok ? multiGroupResult.data : null;
954
+ const inputSubmissions = parentSubmissions.filter(({ tables }) => {
955
+ const hasSpawningGroupTable = tables.some(
956
+ ({ formGroupId }) => formGroupId === spawningGroup?.formGroupId,
957
+ );
958
+ return !hasSpawningGroupTable;
959
+ });
960
+
961
+ // Create model instance
962
+ const model = createLanguageModel({
963
+ gatewayApiKey: config.vercel.aiGatewayApiKey,
964
+ modelId: "openai/gpt-5.2",
965
+ });
966
+
967
+ // Create output submission for each output form
968
+ for (const { formId } of runStep.step.outputForms) {
969
+ const outputSubmission = await createSubmissionWithConversation({
970
+ member,
971
+ data: {
972
+ formId,
973
+ dealId: runStep.run.dealId,
974
+ name:
975
+ runStep.spawnType === "instance"
976
+ ? `${runStep.step.name} - Instance ${runStep.stepRunIndex! + 1}`
977
+ : `${runStep.step.name} output`,
978
+ status: "draft",
979
+ type: "transformation",
980
+ },
981
+ });
982
+ await syncSubmissionToForm({
983
+ member,
984
+ submissionId: outputSubmission.id,
985
+ });
986
+
987
+ // Run LLM-based analysis
988
+ const outputForm = await getForm({ member, formId });
989
+ const analysisResult = await runAnalysisWithLLM({
990
+ member,
991
+ runId: runStep.runId,
992
+ runStepId,
993
+ step: runStep.step,
994
+ inputSubmissions,
995
+ outputForm,
996
+ spawningGroup,
997
+ model,
998
+ });
999
+
1000
+ // Store output
1001
+ if (analysisResult.data) {
1002
+ const storeResult = await storePipelineOutputData({
1003
+ member,
1004
+ outputSubmissionId: outputSubmission.id,
1005
+ outputData: analysisResult.data as Record<
1006
+ string,
1007
+ | Record<string, { value: string | number | null; refId: string } | null>
1008
+ | Record<string, { value: string | number | null; refId: string } | null>[]
1009
+ | null
1010
+ >,
1011
+ });
1012
+
1013
+ if (!storeResult.ok) {
1014
+ throw new Error("Failed to store pipeline output data");
1015
+ }
1016
+ }
1017
+
1018
+ // Link output submission to run step
1019
+ await db.insert(schema.pipelineRunStepOutputSubmission).values({
1020
+ runStepId,
1021
+ submissionId: outputSubmission.id,
1022
+ });
1023
+
1024
+ await updatePipelineRunStepStatus({
1025
+ member,
1026
+ runStepId,
1027
+ status: analysisResult.status,
1028
+ error: analysisResult.error,
1029
+ });
1030
+
1031
+ if (analysisResult.status === "failed") {
1032
+ throw new Error(analysisResult.error || "Analysis step failed");
1033
+ }
1034
+ }
1035
+
1036
+ return {
1037
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1038
+ };
1039
+ } catch (error) {
1040
+ await updatePipelineRunStepStatus({
1041
+ member: { id: memberId } as Member,
1042
+ runStepId,
1043
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1044
+ error: error instanceof Error ? error.message : "Analysis step failed",
1045
+ });
1046
+
1047
+ return {
1048
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1049
+ error: error instanceof Error ? error.message : "Analysis step failed",
1050
+ };
1051
+ }
1052
+ },
1053
+ });
1054
+
1055
+ // ============================================================================
1056
+ // Manual Step Task
1057
+ // ============================================================================
1058
+
1059
+ export const executeManualStepTask = hatchet.task<StepExecutionInput, StepExecutionOutput>({
1060
+ name: "execute-manual-step",
1061
+ timeout: "5m",
1062
+ fn: async (input) => {
1063
+ const { memberId, runStepId, stepId } = input;
1064
+
1065
+ try {
1066
+ const member = await db.query.member.findFirst({
1067
+ where: eq(schema.member.id, memberId),
1068
+ });
1069
+ invariant(member, "Member not found");
1070
+ const runStep = await db.query.pipelineRunStep.findFirst({
1071
+ where: eq(schema.pipelineRunStep.id, runStepId),
1072
+ });
1073
+ invariant(runStep, "Run step not found");
1074
+
1075
+ const stepResult = await getPipelineStepById({ member, stepId });
1076
+ if (!stepResult.ok) {
1077
+ throw new Error(`Step ${stepId} not found`);
1078
+ }
1079
+ const step = stepResult.data;
1080
+ await updatePipelineRunStepStatus({
1081
+ member,
1082
+ runStepId,
1083
+ status: PIPELINE_RUN_STEP_STATUS.RUNNING,
1084
+ });
1085
+
1086
+ // Check if manual output submission has been provided
1087
+ const outputMapping = await db.query.pipelineRunStepOutputSubmission.findFirst({
1088
+ where: eq(schema.pipelineRunStepOutputSubmission.runStepId, runStepId),
1089
+ });
1090
+
1091
+ if (!outputMapping) {
1092
+ // No output submission yet - create a blocker and mark as blocked
1093
+ console.log(
1094
+ `[executeManualStepTask] Step ${step.name} blocked - waiting for manual output submission`,
1095
+ );
1096
+
1097
+ // Check if blocker already exists
1098
+ const existingBlocker = await db.query.pipelineRunStepBlocker.findFirst({
1099
+ where: and(
1100
+ eq(schema.pipelineRunStepBlocker.runStepId, runStepId),
1101
+ eq(schema.pipelineRunStepBlocker.blockerType, "missing_manual_input"),
1102
+ eq(schema.pipelineRunStepBlocker.resolved, false),
1103
+ ),
1104
+ });
1105
+
1106
+ if (!existingBlocker) {
1107
+ await db.insert(schema.pipelineRunStepBlocker).values({
1108
+ runStepId,
1109
+ blockerType: "missing_manual_input",
1110
+ blockerDetails: {
1111
+ type: "missing_manual_input",
1112
+ stepName: step.name,
1113
+ stepDescription: step.description,
1114
+ },
1115
+ resolved: false,
1116
+ });
1117
+ }
1118
+
1119
+ await updatePipelineRunStepStatus({
1120
+ member,
1121
+ runStepId,
1122
+ status: PIPELINE_RUN_STEP_STATUS.BLOCKED,
1123
+ });
1124
+
1125
+ return {
1126
+ status: PIPELINE_RUN_STEP_STATUS.BLOCKED,
1127
+ };
1128
+ }
1129
+
1130
+ // Output submission exists - all dependencies satisfied, mark as completed
1131
+ const result = await updatePipelineRunStepStatus({
1132
+ member,
1133
+ runStepId,
1134
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1135
+ });
1136
+
1137
+ if (!result.ok) {
1138
+ throw new Error("Failed to update pipeline run step status");
1139
+ }
1140
+
1141
+ console.log(
1142
+ `[executeManualStepTask] Step ${step.name} completed - manual output submission provided`,
1143
+ );
1144
+
1145
+ return {
1146
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1147
+ };
1148
+ } catch (error) {
1149
+ await updatePipelineRunStepStatus({
1150
+ member: { id: memberId } as Member,
1151
+ runStepId,
1152
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1153
+ error: error instanceof Error ? error.message : "Manual step failed",
1154
+ });
1155
+
1156
+ return {
1157
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1158
+ error: error instanceof Error ? error.message : "Manual step failed",
1159
+ };
1160
+ }
1161
+ },
1162
+ });
1163
+
1164
+ // ============================================================================
1165
+ // Template Step Task - Dynamic Instance Spawning
1166
+ // ============================================================================
1167
+ export const executeTemplateStepTask = hatchet.task<StepExecutionInput, StepExecutionOutput>({
1168
+ name: "execute-template-step",
1169
+ timeout: "60m", // Templates can spawn many children
1170
+ fn: async (input) => {
1171
+ console.log("[executeTemplateStepTask] Starting template execution...");
1172
+ const { memberId, runStepId, stepId, stepRole } = input;
1173
+
1174
+ try {
1175
+ // Get member
1176
+ const member = await db.query.member.findFirst({
1177
+ where: eq(schema.member.id, memberId),
1178
+ });
1179
+ invariant(member, "Member not found");
1180
+
1181
+ // Get template run step
1182
+ const runStep = await db.query.pipelineRunStep.findFirst({
1183
+ where: eq(schema.pipelineRunStep.id, runStepId),
1184
+ });
1185
+ invariant(runStep, "Template run step not found");
1186
+ invariant(runStep.spawnType === "template", "Run step must be template type");
1187
+
1188
+ // Get step definition
1189
+ const stepResult = await getPipelineStepById({ member, stepId });
1190
+ if (!stepResult.ok) {
1191
+ throw new Error(`Step ${stepId} not found`);
1192
+ }
1193
+ const step = stepResult.data;
1194
+
1195
+ await updatePipelineRunStepStatus({
1196
+ member,
1197
+ runStepId,
1198
+ status: PIPELINE_RUN_STEP_STATUS.RUNNING,
1199
+ });
1200
+
1201
+ // Get parent step runs with dependency config
1202
+ const parentStepRunsResult = await getParentStepRunsWithDependencies({
1203
+ member,
1204
+ runStepId,
1205
+ });
1206
+
1207
+ if (!parentStepRunsResult.ok) {
1208
+ throw new Error("Failed to load parent step runs");
1209
+ }
1210
+ const parentStepRuns = parentStepRunsResult.data;
1211
+
1212
+ // Find dependencies with multiFormGroupId (the spawning trigger)
1213
+ const multiDeps = parentStepRuns.filter((p) => p.multiFormGroupId !== null);
1214
+ if (!multiDeps?.length) return { status: PIPELINE_RUN_STEP_STATUS.COMPLETED };
1215
+ if (multiDeps.length > 1)
1216
+ throw new Error("Multiple multi-group parents found, not supported");
1217
+
1218
+ // Get the unique
1219
+ const multiDep = multiDeps[0];
1220
+ invariant(multiDep, "Multi dependency not found");
1221
+
1222
+ // Get parent's output submission
1223
+ const parentOutputMapping = await db.query.pipelineRunStepOutputSubmission.findFirst({
1224
+ where: eq(schema.pipelineRunStepOutputSubmission.runStepId, multiDep.id),
1225
+ });
1226
+ if (!parentOutputMapping) {
1227
+ throw new Error("Parent step has no output submission");
1228
+ }
1229
+
1230
+ // Get submission groups to spawn instances
1231
+ const groupsResult = await getSubmissionGroups({
1232
+ member,
1233
+ submissionId: parentOutputMapping.submissionId,
1234
+ formGroupId: multiDep.multiFormGroupId!,
1235
+ });
1236
+ if (!groupsResult.ok) {
1237
+ throw new Error("Failed to load submission groups");
1238
+ }
1239
+
1240
+ const groups = groupsResult.data;
1241
+ console.log(
1242
+ `[executeTemplateStepTask] Found ${groups.length} group(s) to spawn for step ${step.name}`,
1243
+ );
1244
+
1245
+ if (groups.length === 0) {
1246
+ console.log("[executeTemplateStepTask] No groups to process, marking template as complete");
1247
+ await updatePipelineRunStepStatus({
1248
+ member,
1249
+ runStepId,
1250
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1251
+ });
1252
+ return { status: PIPELINE_RUN_STEP_STATUS.COMPLETED };
1253
+ }
1254
+
1255
+ // Create instance runSteps for each group
1256
+ const instanceRunSteps = [];
1257
+
1258
+ for (let i = 0; i < groups.length; i++) {
1259
+ const group = groups[i];
1260
+ invariant(group, `Group at index ${i} is undefined`);
1261
+
1262
+ console.log(
1263
+ `[executeTemplateStepTask] Creating instance ${i + 1}/${groups.length} for group ${group.id}`,
1264
+ );
1265
+
1266
+ const instanceResult = await createPipelineRunStep({
1267
+ member,
1268
+ runId: runStep.runId,
1269
+ stepId,
1270
+ spawnType: "instance",
1271
+ submissionGroupId: group.id,
1272
+ stepRunIndex: i,
1273
+ });
1274
+
1275
+ if (!instanceResult.ok) {
1276
+ throw new Error(`Failed to create instance runStep for group ${group.id}`);
1277
+ }
1278
+
1279
+ instanceRunSteps.push(instanceResult.data);
1280
+ }
1281
+
1282
+ console.log(
1283
+ `[executeTemplateStepTask] Created ${instanceRunSteps.length} instance runStep(s), spawning workflows...`,
1284
+ );
1285
+
1286
+ // Spawn child workflows with concurrency limit (max 10 parallel)
1287
+ const limit = pLimit(10);
1288
+ const childPromises = instanceRunSteps.map((instanceRunStep) =>
1289
+ limit(async () => {
1290
+ const instanceInput: StepExecutionInput = {
1291
+ memberId,
1292
+ runId: runStep.runId,
1293
+ runStepId: instanceRunStep.id,
1294
+ stepId,
1295
+ };
1296
+
1297
+ console.log(
1298
+ `[executeTemplateStepTask] Spawning instance workflow: ${stepRole}-step (runStepId: ${instanceRunStep.id})`,
1299
+ );
1300
+
1301
+ // Execute based on step role
1302
+ switch (stepRole) {
1303
+ case "extraction": {
1304
+ const result = await executeExtractionStepTask.run(instanceInput);
1305
+ return result;
1306
+ }
1307
+ case "integration": {
1308
+ const result = await executeIntegrationStepTask.run(instanceInput);
1309
+ return result;
1310
+ }
1311
+ case "analysis": {
1312
+ const result = await executeAnalysisStepTask.run(instanceInput);
1313
+ return result;
1314
+ }
1315
+ case "manual": {
1316
+ const result = await executeManualStepTask.run(instanceInput);
1317
+ return result;
1318
+ }
1319
+ default:
1320
+ throw new Error(`Unknown step role: ${stepRole}`);
1321
+ }
1322
+ }),
1323
+ );
1324
+
1325
+ // Wait for all instances to complete (durable wait)
1326
+ console.log(
1327
+ `[executeTemplateStepTask] Waiting for ${childPromises.length} instance(s) to complete with max 10 concurrent executions...`,
1328
+ );
1329
+ const instanceResults = await Promise.all(childPromises);
1330
+
1331
+ // Check instance results
1332
+ const failedInstances = instanceResults.filter(
1333
+ (r) => r && r.status === PIPELINE_RUN_STEP_STATUS.FAILED,
1334
+ );
1335
+ const completedInstances = instanceResults.filter(
1336
+ (r) => r && r.status === PIPELINE_RUN_STEP_STATUS.COMPLETED,
1337
+ );
1338
+
1339
+ console.log(
1340
+ `[executeTemplateStepTask] Instance results: ${completedInstances.length} completed, ${failedInstances.length} failed`,
1341
+ );
1342
+
1343
+ // Resolve child step blockers now that template is complete
1344
+ await resolveStepBlockersOnCompletion({
1345
+ member,
1346
+ runStepId,
1347
+ });
1348
+
1349
+ // Mark template as complete if all instances succeeded
1350
+ if (failedInstances.length === 0) {
1351
+ await updatePipelineRunStepStatus({
1352
+ member,
1353
+ runStepId,
1354
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1355
+ });
1356
+
1357
+ console.log(
1358
+ `[executeTemplateStepTask] Template step completed successfully with ${instanceResults.length} instance(s)`,
1359
+ );
1360
+
1361
+ return {
1362
+ status: PIPELINE_RUN_STEP_STATUS.COMPLETED,
1363
+ };
1364
+ } else {
1365
+ // Some instances failed
1366
+ await updatePipelineRunStepStatus({
1367
+ member,
1368
+ runStepId,
1369
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1370
+ error: `${failedInstances.length} instance(s) failed`,
1371
+ });
1372
+
1373
+ return {
1374
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1375
+ error: `${failedInstances.length} of ${instanceResults.length} instance(s) failed`,
1376
+ };
1377
+ }
1378
+ } catch (error) {
1379
+ console.error("[executeTemplateStepTask] Error:", error);
1380
+ await updatePipelineRunStepStatus({
1381
+ member: { id: memberId } as Member,
1382
+ runStepId,
1383
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1384
+ error: error instanceof Error ? error.message : "Template step failed",
1385
+ });
1386
+
1387
+ return {
1388
+ status: PIPELINE_RUN_STEP_STATUS.FAILED,
1389
+ error: error instanceof Error ? error.message : "Template step failed",
1390
+ };
1391
+ }
1392
+ },
1393
+ });