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,1165 @@
1
+ import { db, schema } from "@sea/db";
2
+ import type { InsertFormDerived, InsertFormField, InsertFormGroup, Member } from "@sea/db/types";
3
+ import { nanoid } from "@sea/util/id";
4
+ import { invariant, InvariantError } from "@sea/util/invariant";
5
+ import { and, asc, desc, eq, gte, inArray, isNull, sql } from "drizzle-orm";
6
+
7
+ /**
8
+ * Retrieves all non-deleted forms for a member's organization
9
+ * @param member - The member whose organization's forms to retrieve
10
+ * @returns Array of forms with their associated workflows
11
+ */
12
+ export async function getForms({ member }: { member: Member }) {
13
+ const forms = await db.query.form.findMany({
14
+ with: { workflow: true },
15
+ where: and(
16
+ eq(schema.form.organizationId, member.organizationId),
17
+ isNull(schema.form.deletedAt),
18
+ ),
19
+ });
20
+ return forms;
21
+ }
22
+
23
+ /**
24
+ * Retrieves a specific form with its groups, fields, and derived fields
25
+ * @param member - The member whose organization the form belongs to
26
+ * @param formId - The ID of the form to retrieve
27
+ * @returns Form with nested groups, fields, and derived fields, ordered by their order field
28
+ * @throws Error if form is not found
29
+ */
30
+ export async function getForm({ member, formId }: { member: Member; formId: string }) {
31
+ const form = await db.query.form.findFirst({
32
+ where: and(
33
+ eq(schema.form.organizationId, member.organizationId),
34
+ isNull(schema.form.deletedAt),
35
+ eq(schema.form.id, formId),
36
+ ),
37
+ with: {
38
+ groups: {
39
+ with: {
40
+ fields: {
41
+ orderBy: asc(schema.formField.order),
42
+ },
43
+ derived: true,
44
+ },
45
+ orderBy: asc(schema.formGroup.order),
46
+ },
47
+ },
48
+ });
49
+ invariant(form, `no form found for ${formId}`);
50
+ return form;
51
+ }
52
+
53
+ /**
54
+ * Creates a new form with an associated conversation
55
+ * @param member - The member creating the form
56
+ * @param workflowId - The workflow the form belongs to
57
+ * @param name - The name of the form
58
+ * @param hint - Optional hint text for the form
59
+ * @returns The newly created form
60
+ */
61
+ export async function createForm({
62
+ member,
63
+ workflowId,
64
+ name,
65
+ hint = "",
66
+ }: {
67
+ member: Member;
68
+ workflowId: string;
69
+ name: string;
70
+ hint?: string;
71
+ }) {
72
+ return await db.transaction(async (tx) => {
73
+ // Create conversation for the form
74
+ const [conversation] = await tx
75
+ .insert(schema.conversation)
76
+ .values({ organizationId: member.organizationId })
77
+ .returning();
78
+ invariant(conversation);
79
+
80
+ // Create the form
81
+ const [newForm] = await tx
82
+ .insert(schema.form)
83
+ .values({
84
+ workflowId,
85
+ organizationId: member.organizationId,
86
+ conversationId: conversation.id,
87
+ name,
88
+ hint,
89
+ })
90
+ .returning();
91
+ invariant(newForm);
92
+
93
+ return newForm;
94
+ });
95
+ }
96
+
97
+ /**
98
+ * Creates a new form with groups and fields in a single transaction
99
+ * @param member - The member creating the form
100
+ * @param workflowId - The workflow the form belongs to
101
+ * @param name - The name of the form
102
+ * @param hint - Optional hint text for the form
103
+ * @param groups - Array of groups with their fields to create
104
+ * @returns The complete form with all nested groups and fields
105
+ */
106
+ export async function createFormWithGroups({
107
+ member,
108
+ workflowId,
109
+ name,
110
+ hint = "",
111
+ groups,
112
+ }: {
113
+ member: Member;
114
+ workflowId: string;
115
+ name: string;
116
+ hint?: string;
117
+ groups: Array<{
118
+ name: string;
119
+ multi?: boolean;
120
+ hint?: string;
121
+ fields: Array<{
122
+ name: string;
123
+ type?:
124
+ | "string"
125
+ | "string-long"
126
+ | "number"
127
+ | "boolean"
128
+ | "date"
129
+ | "email"
130
+ | "money"
131
+ | "url"
132
+ | "enum";
133
+ hint?: string;
134
+ }>;
135
+ }>;
136
+ }) {
137
+ const { organizationId } = member;
138
+
139
+ return await db.transaction(async (tx) => {
140
+ // Create conversation for the form
141
+ const [conversation] = await tx
142
+ .insert(schema.conversation)
143
+ .values({ organizationId })
144
+ .returning();
145
+ invariant(conversation);
146
+
147
+ // Create the form
148
+ const [newForm] = await tx
149
+ .insert(schema.form)
150
+ .values({
151
+ workflowId,
152
+ organizationId,
153
+ conversationId: conversation.id,
154
+ name,
155
+ hint,
156
+ })
157
+ .returning();
158
+ invariant(newForm);
159
+
160
+ // Create groups and fields
161
+ const formGroups: InsertFormGroup[] = [];
162
+ const formFields: InsertFormField[] = [];
163
+
164
+ groups.forEach((group, groupIndex) => {
165
+ const groupId = nanoid();
166
+ formGroups.push({
167
+ id: groupId,
168
+ formId: newForm.id,
169
+ name: group.name,
170
+ multi: group.multi ?? false,
171
+ hint: group.hint ?? "",
172
+ order: groupIndex,
173
+ });
174
+
175
+ group.fields.forEach((field, fieldIndex) => {
176
+ formFields.push({
177
+ formGroupId: groupId,
178
+ name: field.name,
179
+ type: field.type ?? "string",
180
+ hint: field.hint ?? "",
181
+ order: fieldIndex,
182
+ });
183
+ });
184
+ });
185
+
186
+ // Insert groups and fields
187
+ if (formGroups.length > 0) {
188
+ await tx.insert(schema.formGroup).values(formGroups);
189
+ }
190
+ if (formFields.length > 0) {
191
+ await tx.insert(schema.formField).values(formFields);
192
+ }
193
+
194
+ // Return the complete form with groups and fields
195
+ const completeForm = await tx.query.form.findFirst({
196
+ where: eq(schema.form.id, newForm.id),
197
+ with: {
198
+ groups: {
199
+ with: {
200
+ fields: {
201
+ orderBy: asc(schema.formField.order),
202
+ },
203
+ },
204
+ orderBy: asc(schema.formGroup.order),
205
+ },
206
+ },
207
+ });
208
+
209
+ invariant(completeForm, "Failed to retrieve created form");
210
+ return completeForm;
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Updates a form's name and/or hint
216
+ * @param member - The member whose organization the form belongs to
217
+ * @param formId - The ID of the form to update
218
+ * @param name - Optional new name for the form
219
+ * @param hint - Optional new hint text for the form
220
+ * @returns The updated form
221
+ * @throws Error if form is not found
222
+ */
223
+ export async function updateForm({
224
+ member,
225
+ formId,
226
+ name,
227
+ hint,
228
+ }: {
229
+ member: Member;
230
+ formId: string;
231
+ name?: string;
232
+ hint?: string;
233
+ }) {
234
+ // First verify the form exists and belongs to the organization
235
+ const existingForm = await db.query.form.findFirst({
236
+ where: and(
237
+ eq(schema.form.organizationId, member.organizationId),
238
+ isNull(schema.form.deletedAt),
239
+ eq(schema.form.id, formId),
240
+ ),
241
+ });
242
+ invariant(existingForm, `no form found for ${formId}`);
243
+
244
+ // Build update object with only provided fields
245
+ const updateData: { name?: string; hint?: string } = {};
246
+ if (name !== undefined) updateData.name = name;
247
+ if (hint !== undefined) updateData.hint = hint;
248
+
249
+ const [updatedForm] = await db
250
+ .update(schema.form)
251
+ .set(updateData)
252
+ .where(eq(schema.form.id, formId))
253
+ .returning();
254
+
255
+ return updatedForm;
256
+ }
257
+
258
+ /**
259
+ * Soft deletes a form by setting its deletedAt timestamp
260
+ * @param member - The member whose organization the form belongs to
261
+ * @param formId - The ID of the form to delete
262
+ */
263
+ export async function deleteForm({ member, formId }: { member: Member; formId: string }) {
264
+ await db
265
+ .update(schema.form)
266
+ .set({ deletedAt: new Date() })
267
+ .where(and(eq(schema.form.organizationId, member.organizationId), eq(schema.form.id, formId)));
268
+ }
269
+
270
+ /**
271
+ * Moves a form to a different workflow
272
+ * @param member - The member whose organization the form and workflow belong to
273
+ * @param formId - The ID of the form to move
274
+ * @param workflowId - The ID of the target workflow
275
+ * @returns The updated form with its groups and fields
276
+ * @throws Error if form or workflow is not found
277
+ */
278
+ export async function moveFormToWorkflow({
279
+ member,
280
+ formId,
281
+ workflowId,
282
+ }: {
283
+ member: Member;
284
+ formId: string;
285
+ workflowId: string;
286
+ }) {
287
+ const { organizationId } = member;
288
+
289
+ // First verify the form exists and belongs to the organization
290
+ const existingForm = await db.query.form.findFirst({
291
+ where: and(
292
+ eq(schema.form.organizationId, organizationId),
293
+ isNull(schema.form.deletedAt),
294
+ eq(schema.form.id, formId),
295
+ ),
296
+ });
297
+ invariant(existingForm, `no form found for ${formId}`);
298
+
299
+ // Verify the target workflow exists and belongs to the organization
300
+ const targetWorkflow = await db.query.workflow.findFirst({
301
+ where: and(
302
+ eq(schema.workflow.organizationId, organizationId),
303
+ isNull(schema.workflow.deletedAt),
304
+ eq(schema.workflow.id, workflowId),
305
+ ),
306
+ });
307
+ invariant(targetWorkflow, `no workflow found for ${workflowId}`);
308
+
309
+ // Update the form's workflow
310
+ await db.update(schema.form).set({ workflowId }).where(eq(schema.form.id, formId));
311
+
312
+ // Return the updated form
313
+ return await getForm({ member, formId });
314
+ }
315
+
316
+ /**
317
+ * Creates a copy of an existing form with all its groups, fields, and derived fields
318
+ * @param member - The member whose organization the form belongs to
319
+ * @param formId - The ID of the form to clone
320
+ * @param targetWorkflowId - Optional workflow ID to place the cloned form in (defaults to source form's workflow)
321
+ * @returns Object containing the newly created form
322
+ * @throws Error if form or target workflow is not found
323
+ */
324
+ export async function cloneForm({
325
+ member,
326
+ formId,
327
+ targetWorkflowId,
328
+ }: {
329
+ member: Member;
330
+ formId: string;
331
+ targetWorkflowId?: string;
332
+ }) {
333
+ const existingForm = await db.query.form.findFirst({
334
+ where: and(
335
+ eq(schema.form.organizationId, member.organizationId),
336
+ isNull(schema.form.deletedAt),
337
+ eq(schema.form.id, formId),
338
+ ),
339
+ with: {
340
+ groups: {
341
+ with: { fields: true, derived: true },
342
+ orderBy: asc(schema.formGroup.order),
343
+ },
344
+ },
345
+ });
346
+ invariant(existingForm, `no existing form found for ${formId}`);
347
+
348
+ // If targetWorkflowId is provided, verify access to it
349
+ if (targetWorkflowId) {
350
+ const targetWorkflow = await db.query.workflow.findFirst({
351
+ where: and(
352
+ eq(schema.workflow.organizationId, member.organizationId),
353
+ isNull(schema.workflow.deletedAt),
354
+ eq(schema.workflow.id, targetWorkflowId),
355
+ ),
356
+ });
357
+ invariant(targetWorkflow, `no workflow found for ${targetWorkflowId}`);
358
+ }
359
+
360
+ const newForm = await db.transaction(async (tx) => {
361
+ const [conversation] = await tx
362
+ .insert(schema.conversation)
363
+ .values({ organizationId: member.organizationId })
364
+ .returning();
365
+ invariant(conversation);
366
+ const { id: conversationId } = conversation;
367
+ const [newForm] = await tx
368
+ .insert(schema.form)
369
+ .values({
370
+ ...existingForm,
371
+ id: undefined,
372
+ workflowId: targetWorkflowId || existingForm.workflowId,
373
+ name: `${existingForm.name} (copy)`,
374
+ organizationId: member.organizationId,
375
+ conversationId,
376
+ })
377
+ .returning();
378
+ invariant(newForm);
379
+
380
+ const groups: InsertFormGroup[] = [];
381
+ const fields: InsertFormField[] = [];
382
+ const derived: InsertFormDerived[] = [];
383
+
384
+ existingForm.groups.forEach((group) => {
385
+ const formGroupId = nanoid();
386
+ groups.push({ ...group, id: formGroupId, formId: newForm.id });
387
+
388
+ group.fields.forEach((field) => {
389
+ fields.push({ ...field, id: undefined, formGroupId });
390
+ });
391
+
392
+ // Copy derived fields if any
393
+ group.derived?.forEach((derivedField) => {
394
+ derived.push({ ...derivedField, id: undefined, formGroupId });
395
+ });
396
+ });
397
+ if (groups.length > 0) {
398
+ await tx.insert(schema.formGroup).values(groups);
399
+ }
400
+ if (fields.length > 0) {
401
+ await tx.insert(schema.formField).values(fields);
402
+ }
403
+ if (derived.length > 0) {
404
+ await tx.insert(schema.formDerived).values(derived);
405
+ }
406
+ return newForm;
407
+ });
408
+ return { newForm };
409
+ }
410
+
411
+ /**
412
+ * Retrieves a specific form group within a form
413
+ * @param member - The member whose organization the form belongs to
414
+ * @param formId - The ID of the form containing the group
415
+ * @param formGroupId - The ID of the group to retrieve
416
+ * @returns The form group
417
+ * @throws Error if form or group is not found
418
+ */
419
+ export async function getFormGroup({
420
+ member,
421
+ formId,
422
+ formGroupId,
423
+ }: {
424
+ member: Member;
425
+ formId: string;
426
+ formGroupId: string;
427
+ }) {
428
+ const form = await db.query.form.findFirst({
429
+ where: and(
430
+ eq(schema.form.organizationId, member.organizationId),
431
+ isNull(schema.form.deletedAt),
432
+ eq(schema.form.id, formId),
433
+ ),
434
+ with: {
435
+ groups: {
436
+ where: eq(schema.formGroup.id, formGroupId),
437
+ orderBy: asc(schema.formGroup.order),
438
+ },
439
+ },
440
+ });
441
+ invariant(form, `No form found for ${formId}`);
442
+ const [group] = form.groups;
443
+ invariant(group);
444
+
445
+ return group;
446
+ }
447
+
448
+ /**
449
+ * Creates a new group within a form
450
+ * @param member - The member whose organization the form belongs to
451
+ * @param formId - The ID of the form to add the group to
452
+ * @param name - The name of the group
453
+ * @param multi - Whether this group can have multiple instances (default: false)
454
+ * @param hint - Optional hint text for the group
455
+ * @param order - Optional position in the form (defaults to end)
456
+ * @returns The newly created group
457
+ * @throws Error if form is not found
458
+ */
459
+ export async function createFormGroup({
460
+ member,
461
+ formId,
462
+ name,
463
+ multi = false,
464
+ hint = "",
465
+ order,
466
+ }: {
467
+ member: Member;
468
+ formId: string;
469
+ name: string;
470
+ multi?: boolean;
471
+ hint?: string;
472
+ order?: number;
473
+ }) {
474
+ const form = await db.query.form.findFirst({
475
+ where: and(
476
+ eq(schema.form.organizationId, member.organizationId),
477
+ isNull(schema.form.deletedAt),
478
+ eq(schema.form.id, formId),
479
+ ),
480
+ with: {
481
+ groups: {
482
+ orderBy: asc(schema.formGroup.order),
483
+ },
484
+ },
485
+ });
486
+ invariant(form, `no form found for ${formId}`);
487
+
488
+ const group = await db.transaction(async (tx) => {
489
+ // If order not provided, append to the end
490
+ const maxOrder = form.groups.length ? Math.max(...form.groups.map((g) => g.order)) + 1 : 0;
491
+ const groupOrder = order !== undefined ? order : maxOrder;
492
+
493
+ // If order provided, make sure to shift all subsequent groups forward
494
+ if (order !== undefined) {
495
+ await tx
496
+ .update(schema.formGroup)
497
+ .set({ order: sql`${schema.formGroup.order} + 1` })
498
+ .where(and(eq(schema.formGroup.formId, formId), gte(schema.formGroup.order, order)));
499
+ }
500
+ const [group] = await tx
501
+ .insert(schema.formGroup)
502
+ .values({
503
+ formId,
504
+ name,
505
+ multi,
506
+ hint,
507
+ order: groupOrder,
508
+ })
509
+ .returning();
510
+ return group;
511
+ });
512
+ invariant(group);
513
+
514
+ return group;
515
+ }
516
+
517
+ /**
518
+ * Updates a form group's properties
519
+ * @param member - The member whose organization the form belongs to
520
+ * @param formId - The ID of the form containing the group
521
+ * @param groupId - The ID of the group to update
522
+ * @param name - Optional new name for the group
523
+ * @param multi - Optional new multi value
524
+ * @param hint - Optional new hint text
525
+ * @param order - Optional new position (will shift other groups if needed)
526
+ * @returns The updated group
527
+ * @throws Error if group is not found or member lacks access
528
+ */
529
+ export async function updateFormGroup({
530
+ member,
531
+ formGroupId,
532
+ formId,
533
+ name,
534
+ type,
535
+ multi,
536
+ hint,
537
+ order,
538
+ }: {
539
+ member: Member;
540
+ formId: string;
541
+ formGroupId: string;
542
+ name?: string;
543
+ type?: "custom" | "bank_statement";
544
+ multi?: boolean;
545
+ hint?: string;
546
+ order?: number;
547
+ }) {
548
+ // Validate access
549
+ const group = await getFormGroup({ member, formId, formGroupId });
550
+
551
+ const updateData: Partial<InsertFormGroup> = {};
552
+ if (name !== undefined) updateData.name = name;
553
+ if (type !== undefined) updateData.type = type;
554
+ if (multi !== undefined) updateData.multi = multi;
555
+ if (hint !== undefined) updateData.hint = hint;
556
+ if (order !== undefined) updateData.order = order;
557
+
558
+ if (Object.keys(updateData).length === 0) return group;
559
+ return await db.transaction(async (tx) => {
560
+ if (order !== undefined) {
561
+ await tx
562
+ .update(schema.formGroup)
563
+ .set({ order: sql`${schema.formGroup.order} + 1` })
564
+ .where(and(eq(schema.formGroup.formId, formId), gte(schema.formGroup.order, order)));
565
+ }
566
+ const [updatedGroup] = await tx
567
+ .update(schema.formGroup)
568
+ .set(updateData)
569
+ .where(eq(schema.formGroup.id, group.id))
570
+ .returning();
571
+ invariant(updatedGroup);
572
+ return updatedGroup;
573
+ });
574
+ }
575
+
576
+ /**
577
+ * Deletes a form group and all its fields (via cascade)
578
+ * @param member - The member whose organization the form belongs to
579
+ * @param formId - The ID of the form containing the group
580
+ * @param groupId - The ID of the group to delete
581
+ * @throws Error if form or group is not found
582
+ */
583
+ export async function deleteFormGroup({
584
+ member,
585
+ formId,
586
+ formGroupId,
587
+ }: {
588
+ member: Member;
589
+ formId: string;
590
+ formGroupId: string;
591
+ }) {
592
+ // Validate access
593
+ const group = await getFormGroup({ member, formId, formGroupId });
594
+ await db.delete(schema.formGroup).where(eq(schema.formGroup.id, group.id));
595
+ }
596
+
597
+ /**
598
+ * Retrieves a specific form field and validates access
599
+ * @param member - The member whose organization the form belongs to
600
+ * @param formId - The ID of the form containing the field
601
+ * @param formFieldId - The ID of the field to retrieve
602
+ * @returns The form field
603
+ * @throws InvariantError if field is not found or doesn't belong to the specified form
604
+ */
605
+ export async function getFormField({
606
+ member,
607
+ formId,
608
+ formFieldId,
609
+ }: {
610
+ member: Member;
611
+ formId: string;
612
+ formFieldId: string;
613
+ }) {
614
+ const fieldWithGroup = await db.query.formField.findFirst({
615
+ with: {
616
+ group: {
617
+ with: { form: true },
618
+ },
619
+ },
620
+ where: eq(schema.formField.id, formFieldId),
621
+ });
622
+ invariant(fieldWithGroup, `no formField found for ${formFieldId}`);
623
+
624
+ const { group, ...field } = fieldWithGroup;
625
+ if (group.form.organizationId !== member.organizationId || group.form.id !== formId) {
626
+ throw new InvariantError(`no formField found for ${formFieldId} in form ${formId}`);
627
+ }
628
+
629
+ return field;
630
+ }
631
+
632
+ /**
633
+ * Creates a new field within a form group
634
+ * @param member - The member whose organization the form belongs to
635
+ * @param formId - The ID of the form containing the group
636
+ * @param groupId - The ID of the group to add the field to
637
+ * @param name - The name of the field
638
+ * @param type - The field type (default: "string")
639
+ * @param hint - Optional hint text for the field
640
+ * @param order - Optional position in the group (defaults to end)
641
+ * @returns The newly created field
642
+ * @throws Error if form or group is not found
643
+ */
644
+ export async function createFormField({
645
+ member,
646
+ formId,
647
+ groupId,
648
+ name,
649
+ type = "string",
650
+ hint = "",
651
+ order,
652
+ }: {
653
+ member: Member;
654
+ formId: string;
655
+ groupId: string;
656
+ name: string;
657
+ type?:
658
+ | "string"
659
+ | "string-long"
660
+ | "number"
661
+ | "boolean"
662
+ | "date"
663
+ | "email"
664
+ | "money"
665
+ | "url"
666
+ | "enum";
667
+ hint?: string;
668
+ order?: number;
669
+ }) {
670
+ // Verify the form and group belong to the organization
671
+ const form = await db.query.form.findFirst({
672
+ where: and(
673
+ eq(schema.form.organizationId, member.organizationId),
674
+ isNull(schema.form.deletedAt),
675
+ eq(schema.form.id, formId),
676
+ ),
677
+ with: {
678
+ groups: {
679
+ where: eq(schema.formGroup.id, groupId),
680
+ with: {
681
+ fields: {
682
+ orderBy: asc(schema.formField.order),
683
+ },
684
+ },
685
+ },
686
+ },
687
+ });
688
+ invariant(form, `no form found for ${formId}`);
689
+ const [group] = form.groups;
690
+ invariant(group, `group ${groupId} not found in form ${formId}`);
691
+
692
+ const maxOrder = group.fields.length ? Math.max(...group.fields.map((f) => f.order)) + 1 : 0;
693
+ const fieldOrder = order !== undefined ? order : maxOrder;
694
+ const [field] = await db
695
+ .insert(schema.formField)
696
+ .values({
697
+ formGroupId: groupId,
698
+ name,
699
+ type,
700
+ hint,
701
+ order: fieldOrder,
702
+ })
703
+ .returning();
704
+ invariant(field);
705
+
706
+ return field;
707
+ }
708
+
709
+ /**
710
+ * Updates a form field's properties
711
+ * @param member - The member whose organization the form belongs to
712
+ * @param formId - The ID of the form to which the field belongs to
713
+ * @param formFieldId - The ID of the field to update
714
+ * @param name - Optional new name for the field
715
+ * @param hint - Optional new hint text
716
+ * @param type - Optional new field type
717
+ * @param order - Optional new position (will shift other fields if needed)
718
+ * @returns The updated field
719
+ * @throws Error if field is not found or member lacks access
720
+ */
721
+ export async function updateFormField({
722
+ member,
723
+ formId,
724
+ formFieldId,
725
+ name,
726
+ hint,
727
+ type,
728
+ order,
729
+ }: {
730
+ member: Member;
731
+ formId: string;
732
+ formFieldId: string;
733
+ name?: string;
734
+ hint?: string;
735
+ type?:
736
+ | "string"
737
+ | "string-long"
738
+ | "number"
739
+ | "boolean"
740
+ | "date"
741
+ | "email"
742
+ | "money"
743
+ | "url"
744
+ | "enum";
745
+ order?: number;
746
+ }) {
747
+ const field = await getFormField({ member, formId, formFieldId });
748
+ const updateData: Partial<InsertFormField> = {};
749
+ if (name !== undefined) updateData.name = name;
750
+ if (hint !== undefined) updateData.hint = hint;
751
+ if (type !== undefined) updateData.type = type;
752
+ if (order !== undefined) updateData.order = order;
753
+ if (Object.keys(updateData).length === 0) return field;
754
+
755
+ return await db.transaction(async (tx) => {
756
+ if (order !== undefined) {
757
+ await tx
758
+ .update(schema.formField)
759
+ .set({ order: sql`${schema.formField.order} + 1` })
760
+ .where(
761
+ and(
762
+ eq(schema.formField.formGroupId, field.formGroupId),
763
+ gte(schema.formField.order, order),
764
+ ),
765
+ );
766
+ }
767
+ const [formField] = await tx
768
+ .update(schema.formField)
769
+ .set(updateData)
770
+ .where(eq(schema.formField.id, formFieldId))
771
+ .returning();
772
+ invariant(formField);
773
+ return formField;
774
+ });
775
+ }
776
+
777
+ /**
778
+ * Updates only a form field's hint text
779
+ * @param member - The member whose organization the form belongs to
780
+ * @param formFieldId - The ID of the field to update
781
+ * @param hint - The new hint text
782
+ * @throws Error if field is not found or member lacks access
783
+ */
784
+ export async function updateFormFieldHint({
785
+ member,
786
+ formFieldId,
787
+ hint,
788
+ }: {
789
+ member: Member;
790
+ formFieldId: string;
791
+ hint: string;
792
+ }) {
793
+ const field = await db.query.formField.findFirst({
794
+ where: eq(schema.formField.id, formFieldId),
795
+ with: { group: { with: { form: true } } },
796
+ });
797
+ if (field?.group.form.organizationId !== member.organizationId) {
798
+ throw new InvariantError(`formField not found for ${formFieldId}`);
799
+ }
800
+
801
+ // Get the field to validate access
802
+ await db.update(schema.formField).set({ hint }).where(eq(schema.formField.id, field.id));
803
+ }
804
+
805
+ /**
806
+ * Deletes a form field
807
+ * @param member - The member whose organization the form belongs to
808
+ * @param formId - The ID of the form containing the field
809
+ * @param fieldId - The ID of the field to delete
810
+ * @throws Error if form or field is not found
811
+ */
812
+ export async function deleteFormField({
813
+ member,
814
+ formId,
815
+ formFieldId,
816
+ }: {
817
+ member: Member;
818
+ formId: string;
819
+ formFieldId: string;
820
+ }) {
821
+ // Get the field to validate access
822
+ const field = await getFormField({ member, formId, formFieldId });
823
+ await db.delete(schema.formField).where(eq(schema.formField.id, field.id));
824
+ }
825
+
826
+ /**
827
+ * Creates a derived field within a form group (computed/AI-generated field)
828
+ * @param member - The member whose organization the form belongs to
829
+ * @param formId - The ID of the form containing the group
830
+ * @param groupId - The ID of the group to add the derived field to
831
+ * @param name - The name of the derived field
832
+ * @param prompt - Optional prompt text for generating the derived value
833
+ * @returns The newly created derived field
834
+ * @throws Error if form or group is not found
835
+ */
836
+ export async function createFormDerived({
837
+ member,
838
+ formId,
839
+ groupId,
840
+ name,
841
+ prompt = "",
842
+ }: {
843
+ member: Member;
844
+ formId: string;
845
+ groupId: string;
846
+ name: string;
847
+ prompt?: string;
848
+ }) {
849
+ // Verify the form and group belong to the organization
850
+ const form = await db.query.form.findFirst({
851
+ where: and(
852
+ eq(schema.form.organizationId, member.organizationId),
853
+ isNull(schema.form.deletedAt),
854
+ eq(schema.form.id, formId),
855
+ ),
856
+ with: {
857
+ groups: {
858
+ where: eq(schema.formGroup.id, groupId),
859
+ },
860
+ },
861
+ });
862
+ invariant(form, `no form found for ${formId}`);
863
+ invariant(form.groups.length > 0, `group ${groupId} not found in form ${formId}`);
864
+
865
+ const [derived] = await db
866
+ .insert(schema.formDerived)
867
+ .values({
868
+ formGroupId: groupId,
869
+ name,
870
+ prompt,
871
+ })
872
+ .returning();
873
+ invariant(derived);
874
+
875
+ return derived;
876
+ }
877
+
878
+ /**
879
+ * Updates a derived field's properties
880
+ * @param member - The member whose organization the form belongs to
881
+ * @param derivedId - The ID of the derived field to update
882
+ * @param name - Optional new name for the derived field
883
+ * @param prompt - Optional new prompt text
884
+ * @returns The updated derived field
885
+ * @throws Error if derived field is not found or member lacks access
886
+ */
887
+ export async function updateFormDerived({
888
+ member,
889
+ formId,
890
+ derivedId,
891
+ name,
892
+ prompt,
893
+ }: {
894
+ member: Member;
895
+ formId: string;
896
+ derivedId: string;
897
+ name?: string;
898
+ prompt?: string;
899
+ }) {
900
+ // Verify the form and derived field belong to the organization
901
+ const formDerived = await db.query.formDerived.findFirst({
902
+ with: {
903
+ group: {
904
+ with: {
905
+ form: true,
906
+ },
907
+ },
908
+ },
909
+ where: eq(schema.formDerived.id, derivedId),
910
+ });
911
+ invariant(formDerived, `no formDerived found for ${derivedId}`);
912
+ const { group, ...currentDerived } = formDerived;
913
+
914
+ if (group.form.organizationId !== member.organizationId) {
915
+ throw new InvariantError(`no form found for ${formId}`);
916
+ }
917
+
918
+ const updateData: Partial<InsertFormDerived> = {};
919
+ if (name !== undefined) updateData.name = name;
920
+ if (prompt !== undefined) updateData.prompt = prompt;
921
+
922
+ if (Object.keys(updateData).length === 0) return currentDerived;
923
+ const [updatedFormDerived] = await db
924
+ .update(schema.formDerived)
925
+ .set(updateData)
926
+ .where(eq(schema.formDerived.id, derivedId))
927
+ .returning();
928
+
929
+ return updatedFormDerived;
930
+ }
931
+
932
+ /**
933
+ * Deletes a derived field
934
+ * @param member - The member whose organization the form belongs to
935
+ * @param formId - The ID of the form containing the derived field
936
+ * @param derivedId - The ID of the derived field to delete
937
+ * @throws Error if form or derived field is not found
938
+ */
939
+ export async function deleteFormDerived({
940
+ member,
941
+ formId,
942
+ derivedId,
943
+ }: {
944
+ member: Member;
945
+ formId: string;
946
+ derivedId: string;
947
+ }) {
948
+ // Verify the form and derived field belong to the organization
949
+ const form = await db.query.form.findFirst({
950
+ where: and(
951
+ eq(schema.form.organizationId, member.organizationId),
952
+ isNull(schema.form.deletedAt),
953
+ eq(schema.form.id, formId),
954
+ ),
955
+ with: {
956
+ groups: {
957
+ with: {
958
+ derived: {
959
+ where: eq(schema.formDerived.id, derivedId),
960
+ },
961
+ },
962
+ },
963
+ },
964
+ });
965
+ invariant(form, `no form found for ${formId}`);
966
+
967
+ const derivedBelongsToForm = form.groups.some((group) =>
968
+ group.derived.some((d) => d.id === derivedId),
969
+ );
970
+ invariant(derivedBelongsToForm, `derived field ${derivedId} not found in form ${formId}`);
971
+
972
+ await db.delete(schema.formDerived).where(eq(schema.formDerived.id, derivedId));
973
+ }
974
+
975
+ /**
976
+ * Creates or updates a merged form for a template based on its workflow
977
+ * Combines all groups from all forms in the workflow into a single form
978
+ * @param member - The member whose organization the template belongs to
979
+ * @param templateId - The ID of the template
980
+ * @param workflowId - The ID of the workflow to merge forms from
981
+ * @param existingMergedFormId - Optional ID of existing merged form to update
982
+ * @returns The merged form ID and a hash of the workflow's forms for staleness checking
983
+ */
984
+ export async function getOrCreateMergedFormForTemplate({
985
+ member,
986
+ templateId,
987
+ workflowId,
988
+ existingMergedFormId,
989
+ }: {
990
+ member: Member;
991
+ templateId: string;
992
+ workflowId: string;
993
+ existingMergedFormId?: string | null;
994
+ }): Promise<{ formId: string; formHash: string }> {
995
+ // Get all forms in the workflow with their groups and fields
996
+ const workflowForms = await db.query.form.findMany({
997
+ where: and(
998
+ eq(schema.form.workflowId, workflowId),
999
+ eq(schema.form.organizationId, member.organizationId),
1000
+ isNull(schema.form.deletedAt),
1001
+ ),
1002
+ with: {
1003
+ groups: {
1004
+ with: {
1005
+ fields: {
1006
+ orderBy: asc(schema.formField.order),
1007
+ },
1008
+ derived: true,
1009
+ },
1010
+ orderBy: asc(schema.formGroup.order),
1011
+ },
1012
+ },
1013
+ orderBy: asc(schema.form.createdAt),
1014
+ });
1015
+
1016
+ if (workflowForms.length === 0) {
1017
+ throw new InvariantError(`No forms found in workflow ${workflowId}`);
1018
+ }
1019
+
1020
+ // Create a hash of form IDs and their updated timestamps to detect changes
1021
+ const formHash = workflowForms.map((f) => `${f.id}:${f.updatedAt.getTime()}`).join("|");
1022
+
1023
+ // Check if existing merged form is still valid
1024
+ if (existingMergedFormId) {
1025
+ const existingForm = await db.query.form.findFirst({
1026
+ where: and(
1027
+ eq(schema.form.id, existingMergedFormId),
1028
+ eq(schema.form.organizationId, member.organizationId),
1029
+ isNull(schema.form.deletedAt),
1030
+ ),
1031
+ });
1032
+
1033
+ // If form exists with the same name pattern, check if it's still valid
1034
+ // We store the hash in the form name for now since metadata field doesn't exist
1035
+ if (existingForm && existingForm.name.includes(formHash.substring(0, 10))) {
1036
+ return { formId: existingMergedFormId, formHash };
1037
+ }
1038
+ }
1039
+
1040
+ // Need to create new merged form
1041
+ return await db.transaction(async (tx) => {
1042
+ // Create conversation for the merged form
1043
+ const [conversation] = await tx
1044
+ .insert(schema.conversation)
1045
+ .values({ organizationId: member.organizationId })
1046
+ .returning();
1047
+ invariant(conversation);
1048
+
1049
+ // Get workflow name for form name
1050
+ const workflow = await tx.query.workflow.findFirst({
1051
+ where: eq(schema.workflow.id, workflowId),
1052
+ });
1053
+
1054
+ // Create the merged form
1055
+ const [mergedForm] = await tx
1056
+ .insert(schema.form)
1057
+ .values({
1058
+ organizationId: member.organizationId,
1059
+ workflowId,
1060
+ conversationId: conversation.id,
1061
+ name: `Merged: ${workflow?.name || workflowId} [${formHash.substring(0, 10)}]`,
1062
+ hint: `Auto-generated merged form for template ${templateId}`,
1063
+ })
1064
+ .returning();
1065
+ invariant(mergedForm);
1066
+
1067
+ // Merge all groups from all forms
1068
+ let groupOrder = 0;
1069
+ for (const sourceForm of workflowForms) {
1070
+ for (const sourceGroup of sourceForm.groups) {
1071
+ // Insert group with new IDs
1072
+ const [newGroup] = await tx
1073
+ .insert(schema.formGroup)
1074
+ .values({
1075
+ formId: mergedForm.id,
1076
+ name: `${sourceForm.name} - ${sourceGroup.name}`,
1077
+ order: groupOrder++,
1078
+ type: sourceGroup.type,
1079
+ multi: sourceGroup.multi,
1080
+ hint: sourceGroup.hint,
1081
+ })
1082
+ .returning();
1083
+ invariant(newGroup);
1084
+
1085
+ // Copy all fields
1086
+ for (const sourceField of sourceGroup.fields) {
1087
+ await tx.insert(schema.formField).values({
1088
+ formGroupId: newGroup.id,
1089
+ name: sourceField.name,
1090
+ type: sourceField.type,
1091
+ order: sourceField.order,
1092
+ hint: sourceField.hint,
1093
+ options: sourceField.options,
1094
+ });
1095
+ }
1096
+
1097
+ // Copy all derived fields
1098
+ for (const sourceDerived of sourceGroup.derived) {
1099
+ await tx.insert(schema.formDerived).values({
1100
+ formGroupId: newGroup.id,
1101
+ name: sourceDerived.name,
1102
+ prompt: sourceDerived.prompt,
1103
+ });
1104
+ }
1105
+ }
1106
+ }
1107
+
1108
+ return { formId: mergedForm.id, formHash };
1109
+ });
1110
+ }
1111
+
1112
+ /**
1113
+ * Get all forms for an organization with pagination
1114
+ */
1115
+ export async function getFormsForOrganization({
1116
+ member,
1117
+ limit = 100,
1118
+ }: {
1119
+ member: Member;
1120
+ limit?: number;
1121
+ }) {
1122
+ const forms = await db.query.form.findMany({
1123
+ where: and(
1124
+ eq(schema.form.organizationId, member.organizationId),
1125
+ isNull(schema.form.deletedAt),
1126
+ ),
1127
+ columns: {
1128
+ id: true,
1129
+ name: true,
1130
+ updatedAt: true,
1131
+ },
1132
+ orderBy: [desc(schema.form.updatedAt)],
1133
+ limit,
1134
+ });
1135
+
1136
+ return { ok: true, data: forms };
1137
+ }
1138
+
1139
+ /**
1140
+ * Get multiple forms by their IDs
1141
+ */
1142
+ export async function getFormsByIds({ member, formIds }: { member: Member; formIds: string[] }) {
1143
+ if (formIds.length === 0) {
1144
+ return { ok: true, data: [] };
1145
+ }
1146
+
1147
+ const forms = await db.query.form.findMany({
1148
+ where: and(
1149
+ eq(schema.form.organizationId, member.organizationId),
1150
+ inArray(schema.form.id, formIds),
1151
+ isNull(schema.form.deletedAt),
1152
+ ),
1153
+ columns: {
1154
+ id: true,
1155
+ name: true,
1156
+ organizationId: true,
1157
+ },
1158
+ });
1159
+
1160
+ if (forms.length !== formIds.length) {
1161
+ return { ok: false, error: "not-found" };
1162
+ }
1163
+
1164
+ return { ok: true, data: forms };
1165
+ }