@useatlas/create 0.0.5 → 0.0.7

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 (952) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/index.ts +253 -36
  4. package/package.json +4 -4
  5. package/templates/docker/Dockerfile +1 -1
  6. package/templates/docker/Dockerfile.sidecar +1 -1
  7. package/templates/docker/bin/__tests__/duckdb-ingest.test.ts +17 -14
  8. package/templates/docker/bin/__tests__/failure-threshold.test.ts +148 -0
  9. package/templates/docker/bin/__tests__/fatal-error-propagation.test.ts +267 -0
  10. package/templates/docker/bin/__tests__/profiler-heuristics.test.ts +5 -5
  11. package/templates/docker/bin/__tests__/schema-drift.test.ts +39 -0
  12. package/templates/docker/bin/atlas.ts +981 -1819
  13. package/templates/docker/bin/benchmark.ts +14 -16
  14. package/templates/docker/bin/enrich.ts +7 -2
  15. package/templates/docker/brand.css +13 -0
  16. package/templates/docker/data/cybersec-semantic/catalog.yml +222 -0
  17. package/templates/docker/data/cybersec-semantic/entities/alerts.yml +195 -0
  18. package/templates/docker/data/cybersec-semantic/entities/assets.yml +191 -0
  19. package/templates/docker/data/cybersec-semantic/entities/compliance_assessments.yml +170 -0
  20. package/templates/docker/data/cybersec-semantic/entities/incidents.yml +219 -0
  21. package/templates/docker/data/cybersec-semantic/entities/organizations.yml +136 -0
  22. package/templates/docker/data/cybersec-semantic/entities/plans.yml +114 -0
  23. package/templates/docker/data/cybersec-semantic/entities/remediation_actions.yml +212 -0
  24. package/templates/docker/data/cybersec-semantic/entities/scan_results.yml +215 -0
  25. package/templates/docker/data/cybersec-semantic/entities/scans.yml +180 -0
  26. package/templates/docker/data/cybersec-semantic/entities/subscriptions.yml +184 -0
  27. package/templates/docker/data/cybersec-semantic/entities/users.yml +140 -0
  28. package/templates/docker/data/cybersec-semantic/entities/vulnerabilities.yml +154 -0
  29. package/templates/docker/data/cybersec-semantic/glossary.yml +207 -0
  30. package/templates/docker/data/cybersec-semantic/metrics/business.yml +148 -0
  31. package/templates/docker/data/cybersec-semantic/metrics/compliance.yml +138 -0
  32. package/templates/docker/data/cybersec-semantic/metrics/security.yml +181 -0
  33. package/templates/docker/data/cybersec.sql +8 -8
  34. package/templates/docker/data/demo.sql +3 -0
  35. package/templates/docker/data/ecommerce-semantic/catalog.yml +221 -0
  36. package/templates/docker/data/ecommerce-semantic/entities/categories.yml +91 -0
  37. package/templates/docker/data/ecommerce-semantic/entities/customers.yml +133 -0
  38. package/templates/docker/data/ecommerce-semantic/entities/email_campaigns.yml +119 -0
  39. package/templates/docker/data/ecommerce-semantic/entities/inventory_levels.yml +153 -0
  40. package/templates/docker/data/ecommerce-semantic/entities/order_items.yml +159 -0
  41. package/templates/docker/data/ecommerce-semantic/entities/orders.yml +199 -0
  42. package/templates/docker/data/ecommerce-semantic/entities/payments.yml +140 -0
  43. package/templates/docker/data/ecommerce-semantic/entities/product_reviews.yml +155 -0
  44. package/templates/docker/data/ecommerce-semantic/entities/products.yml +178 -0
  45. package/templates/docker/data/ecommerce-semantic/entities/promotions.yml +171 -0
  46. package/templates/docker/data/ecommerce-semantic/entities/returns.yml +144 -0
  47. package/templates/docker/data/ecommerce-semantic/entities/sellers.yml +124 -0
  48. package/templates/docker/data/ecommerce-semantic/entities/shipments.yml +159 -0
  49. package/templates/docker/data/ecommerce-semantic/glossary.yml +193 -0
  50. package/templates/docker/data/ecommerce-semantic/metrics/customers.yml +116 -0
  51. package/templates/docker/data/ecommerce-semantic/metrics/operations.yml +131 -0
  52. package/templates/docker/data/ecommerce-semantic/metrics/revenue.yml +120 -0
  53. package/templates/docker/docs/deploy.md +2 -1
  54. package/templates/docker/ee/src/__mocks__/internal.ts +170 -0
  55. package/templates/docker/ee/src/audit/purge-scheduler.ts +113 -0
  56. package/templates/docker/ee/src/audit/retention.ts +467 -0
  57. package/templates/docker/ee/src/auth/ip-allowlist.ts +367 -0
  58. package/templates/docker/ee/src/auth/roles.ts +562 -0
  59. package/templates/docker/ee/src/auth/scim.ts +343 -0
  60. package/templates/docker/ee/src/auth/sso.ts +538 -0
  61. package/templates/docker/ee/src/backups/engine.ts +355 -0
  62. package/templates/docker/ee/src/backups/index.ts +26 -0
  63. package/templates/docker/ee/src/backups/restore.ts +169 -0
  64. package/templates/docker/ee/src/backups/scheduler.ts +153 -0
  65. package/templates/docker/ee/src/backups/verify.ts +124 -0
  66. package/templates/docker/ee/src/branding/white-label.ts +228 -0
  67. package/templates/docker/ee/src/compliance/masking.ts +477 -0
  68. package/templates/docker/ee/src/compliance/patterns.ts +16 -0
  69. package/templates/docker/ee/src/compliance/pii-detection.ts +217 -0
  70. package/templates/docker/ee/src/compliance/reports.ts +402 -0
  71. package/templates/docker/ee/src/deploy-mode.ts +37 -0
  72. package/templates/docker/ee/src/governance/approval.ts +699 -0
  73. package/templates/docker/ee/src/index.ts +74 -0
  74. package/templates/docker/ee/src/platform/domains.ts +562 -0
  75. package/templates/docker/ee/src/platform/model-routing.ts +382 -0
  76. package/templates/docker/ee/src/platform/residency.ts +265 -0
  77. package/templates/docker/ee/src/sla/alerting.ts +382 -0
  78. package/templates/docker/ee/src/sla/index.ts +12 -0
  79. package/templates/docker/ee/src/sla/metrics.ts +275 -0
  80. package/templates/docker/ee/src/test-setup.ts +1 -0
  81. package/templates/docker/next.config.ts +4 -1
  82. package/templates/docker/package.json +49 -29
  83. package/templates/docker/sidecar/Dockerfile +1 -1
  84. package/templates/docker/src/api/index.ts +336 -24
  85. package/templates/docker/src/api/routes/actions.ts +443 -176
  86. package/templates/docker/src/api/routes/admin-abuse.ts +219 -0
  87. package/templates/docker/src/api/routes/admin-approval.ts +418 -0
  88. package/templates/docker/src/api/routes/admin-audit-retention.ts +405 -0
  89. package/templates/docker/src/api/routes/admin-auth.ts +122 -0
  90. package/templates/docker/src/api/routes/admin-branding.ts +252 -0
  91. package/templates/docker/src/api/routes/admin-compliance.ts +352 -0
  92. package/templates/docker/src/api/routes/admin-domains.ts +334 -0
  93. package/templates/docker/src/api/routes/admin-integrations.ts +2667 -0
  94. package/templates/docker/src/api/routes/admin-ip-allowlist.ts +261 -0
  95. package/templates/docker/src/api/routes/admin-learned-patterns.ts +525 -0
  96. package/templates/docker/src/api/routes/admin-model-config.ts +252 -0
  97. package/templates/docker/src/api/routes/admin-onboarding-emails.ts +145 -0
  98. package/templates/docker/src/api/routes/admin-orgs.ts +710 -0
  99. package/templates/docker/src/api/routes/admin-prompts.ts +694 -0
  100. package/templates/docker/src/api/routes/admin-residency.ts +570 -0
  101. package/templates/docker/src/api/routes/admin-roles.ts +296 -0
  102. package/templates/docker/src/api/routes/admin-router.ts +120 -0
  103. package/templates/docker/src/api/routes/admin-sandbox.ts +417 -0
  104. package/templates/docker/src/api/routes/admin-scim.ts +262 -0
  105. package/templates/docker/src/api/routes/admin-sso.ts +545 -0
  106. package/templates/docker/src/api/routes/admin-suggestions.ts +176 -0
  107. package/templates/docker/src/api/routes/admin-usage.ts +310 -0
  108. package/templates/docker/src/api/routes/admin.ts +4156 -898
  109. package/templates/docker/src/api/routes/auth-preamble.ts +105 -0
  110. package/templates/docker/src/api/routes/billing.ts +397 -0
  111. package/templates/docker/src/api/routes/chat.ts +597 -334
  112. package/templates/docker/src/api/routes/conversations.ts +987 -132
  113. package/templates/docker/src/api/routes/demo.ts +673 -0
  114. package/templates/docker/src/api/routes/discord.ts +274 -0
  115. package/templates/docker/src/api/routes/ee-error-handler.ts +32 -0
  116. package/templates/docker/src/api/routes/health.ts +129 -14
  117. package/templates/docker/src/api/routes/middleware.ts +244 -0
  118. package/templates/docker/src/api/routes/onboarding-emails.ts +134 -0
  119. package/templates/docker/src/api/routes/onboarding.ts +1109 -0
  120. package/templates/docker/src/api/routes/openapi.ts +184 -1597
  121. package/templates/docker/src/api/routes/platform-admin.ts +760 -0
  122. package/templates/docker/src/api/routes/platform-backups.ts +436 -0
  123. package/templates/docker/src/api/routes/platform-domains.ts +235 -0
  124. package/templates/docker/src/api/routes/platform-residency.ts +257 -0
  125. package/templates/docker/src/api/routes/platform-sla.ts +379 -0
  126. package/templates/docker/src/api/routes/prompts.ts +221 -0
  127. package/templates/docker/src/api/routes/public-branding.ts +106 -0
  128. package/templates/docker/src/api/routes/query.ts +330 -219
  129. package/templates/docker/src/api/routes/scheduled-tasks.ts +393 -297
  130. package/templates/docker/src/api/routes/semantic.ts +179 -0
  131. package/templates/docker/src/api/routes/sessions.ts +210 -0
  132. package/templates/docker/src/api/routes/shared-domains.ts +98 -0
  133. package/templates/docker/src/api/routes/shared-schemas.ts +139 -0
  134. package/templates/docker/src/api/routes/slack.ts +209 -52
  135. package/templates/docker/src/api/routes/suggestions.ts +233 -0
  136. package/templates/docker/src/api/routes/tables.ts +67 -0
  137. package/templates/docker/src/api/routes/teams.ts +222 -0
  138. package/templates/docker/src/api/routes/validate-sql.ts +188 -0
  139. package/templates/docker/src/api/routes/validation-hook.ts +62 -0
  140. package/templates/docker/src/api/routes/widget-loader.ts +356 -0
  141. package/templates/docker/src/api/routes/widget.ts +428 -0
  142. package/templates/docker/src/api/routes/wizard.ts +852 -0
  143. package/templates/docker/src/api/server.ts +187 -69
  144. package/templates/docker/src/app/error.tsx +5 -2
  145. package/templates/docker/src/app/globals.css +1 -1
  146. package/templates/docker/src/app/layout.tsx +7 -2
  147. package/templates/docker/src/app/page.tsx +39 -5
  148. package/templates/docker/src/components/data-table/data-table-column-header.tsx +99 -0
  149. package/templates/docker/src/components/data-table/data-table-date-filter.tsx +225 -0
  150. package/templates/docker/src/components/data-table/data-table-expandable.tsx +125 -0
  151. package/templates/docker/src/components/data-table/data-table-faceted-filter.tsx +189 -0
  152. package/templates/docker/src/components/data-table/data-table-pagination.tsx +112 -0
  153. package/templates/docker/src/components/data-table/data-table-range-filter.tsx +122 -0
  154. package/templates/docker/src/components/data-table/data-table-slider-filter.tsx +256 -0
  155. package/templates/docker/src/components/data-table/data-table-sort-list.tsx +407 -0
  156. package/templates/docker/src/components/data-table/data-table-toolbar.tsx +149 -0
  157. package/templates/docker/src/components/data-table/data-table-view-options.tsx +89 -0
  158. package/templates/docker/src/components/data-table/data-table.tsx +105 -0
  159. package/templates/docker/src/components/form-dialog.tsx +135 -0
  160. package/templates/docker/src/components/ui/accordion.tsx +66 -0
  161. package/templates/docker/src/components/ui/calendar.tsx +220 -0
  162. package/templates/docker/src/components/ui/checkbox.tsx +32 -0
  163. package/templates/docker/src/components/ui/faceted.tsx +283 -0
  164. package/templates/docker/src/components/ui/form.tsx +167 -0
  165. package/templates/docker/src/components/ui/label.tsx +24 -0
  166. package/templates/docker/src/components/ui/popover.tsx +89 -0
  167. package/templates/docker/src/components/ui/progress.tsx +31 -0
  168. package/templates/docker/src/components/ui/scroll-area.tsx +6 -2
  169. package/templates/docker/src/components/ui/slider.tsx +63 -0
  170. package/templates/docker/src/components/ui/sortable.tsx +581 -0
  171. package/templates/docker/src/components/ui/switch.tsx +35 -0
  172. package/templates/docker/src/components/ui/textarea.tsx +18 -0
  173. package/templates/docker/src/config/data-table.ts +82 -0
  174. package/templates/docker/src/env-check.ts +74 -0
  175. package/templates/docker/src/hooks/use-callback-ref.ts +27 -0
  176. package/templates/docker/src/hooks/use-data-table.ts +316 -0
  177. package/templates/docker/src/hooks/use-debounced-callback.ts +28 -0
  178. package/templates/docker/src/lib/action-types.ts +7 -41
  179. package/templates/docker/src/lib/agent-query.ts +4 -2
  180. package/templates/docker/src/lib/agent.ts +363 -31
  181. package/templates/docker/src/lib/auth/admin-permissions.ts +38 -0
  182. package/templates/docker/src/lib/auth/audit.ts +19 -4
  183. package/templates/docker/src/lib/auth/byot.ts +3 -3
  184. package/templates/docker/src/lib/auth/client.ts +33 -3
  185. package/templates/docker/src/lib/auth/detect.ts +29 -8
  186. package/templates/docker/src/lib/auth/managed.ts +104 -14
  187. package/templates/docker/src/lib/auth/middleware.ts +53 -6
  188. package/templates/docker/src/lib/auth/migrate.ts +140 -15
  189. package/templates/docker/src/lib/auth/oauth-state.ts +123 -0
  190. package/templates/docker/src/lib/auth/org-permissions.ts +55 -0
  191. package/templates/docker/src/lib/auth/permissions.ts +26 -19
  192. package/templates/docker/src/lib/auth/server.ts +355 -9
  193. package/templates/docker/src/lib/auth/simple-key.ts +3 -3
  194. package/templates/docker/src/lib/auth/types.ts +15 -21
  195. package/templates/docker/src/lib/billing/enforcement.ts +368 -0
  196. package/templates/docker/src/lib/billing/plans.ts +155 -0
  197. package/templates/docker/src/lib/cache/index.ts +92 -0
  198. package/templates/docker/src/lib/cache/keys.ts +30 -0
  199. package/templates/docker/src/lib/cache/lru.ts +79 -0
  200. package/templates/docker/src/lib/cache/types.ts +31 -0
  201. package/templates/docker/src/lib/compose-refs.ts +62 -0
  202. package/templates/docker/src/lib/config.ts +563 -11
  203. package/templates/docker/src/lib/connection-types.ts +9 -0
  204. package/templates/docker/src/lib/conversation-types.ts +1 -25
  205. package/templates/docker/src/lib/conversations.ts +345 -14
  206. package/templates/docker/src/lib/data-table.ts +61 -0
  207. package/templates/docker/src/lib/db/connection.ts +793 -39
  208. package/templates/docker/src/lib/db/internal.ts +985 -139
  209. package/templates/docker/src/lib/db/migrate.ts +295 -0
  210. package/templates/docker/src/lib/db/migrations/0000_baseline.sql +703 -0
  211. package/templates/docker/src/lib/db/migrations/0001_teams_installations.sql +14 -0
  212. package/templates/docker/src/lib/db/migrations/0002_discord_installations.sql +14 -0
  213. package/templates/docker/src/lib/db/migrations/0003_telegram_installations.sql +15 -0
  214. package/templates/docker/src/lib/db/migrations/0004_sandbox_credentials.sql +18 -0
  215. package/templates/docker/src/lib/db/migrations/0005_oauth_state.sql +16 -0
  216. package/templates/docker/src/lib/db/migrations/0006_byot_credentials.sql +14 -0
  217. package/templates/docker/src/lib/db/migrations/0007_gchat_installations.sql +15 -0
  218. package/templates/docker/src/lib/db/migrations/0008_github_installations.sql +14 -0
  219. package/templates/docker/src/lib/db/migrations/0009_linear_installations.sql +15 -0
  220. package/templates/docker/src/lib/db/migrations/0010_whatsapp_installations.sql +14 -0
  221. package/templates/docker/src/lib/db/migrations/0011_email_installations.sql +16 -0
  222. package/templates/docker/src/lib/db/migrations/0012_region_migrations.sql +25 -0
  223. package/templates/docker/src/lib/db/schema.ts +1120 -0
  224. package/templates/docker/src/lib/db/source-rate-limit.ts +89 -139
  225. package/templates/docker/src/lib/demo.ts +308 -0
  226. package/templates/docker/src/lib/discord/store.ts +225 -0
  227. package/templates/docker/src/lib/effect/ai.ts +243 -0
  228. package/templates/docker/src/lib/effect/errors.ts +234 -0
  229. package/templates/docker/src/lib/effect/hono.ts +454 -0
  230. package/templates/docker/src/lib/effect/index.ts +137 -0
  231. package/templates/docker/src/lib/effect/layers.ts +496 -0
  232. package/templates/docker/src/lib/effect/services.ts +776 -0
  233. package/templates/docker/src/lib/effect/sql.ts +178 -0
  234. package/templates/docker/src/lib/effect/toolkit.ts +123 -0
  235. package/templates/docker/src/lib/email/delivery.ts +232 -0
  236. package/templates/docker/src/lib/email/engine.ts +349 -0
  237. package/templates/docker/src/lib/email/hooks.ts +107 -0
  238. package/templates/docker/src/lib/email/index.ts +16 -0
  239. package/templates/docker/src/lib/email/scheduler.ts +72 -0
  240. package/templates/docker/src/lib/email/sequence.ts +73 -0
  241. package/templates/docker/src/lib/email/store.ts +163 -0
  242. package/templates/docker/src/lib/email/templates.ts +215 -0
  243. package/templates/docker/src/lib/format.ts +67 -0
  244. package/templates/docker/src/lib/gchat/store.ts +202 -0
  245. package/templates/docker/src/lib/github/store.ts +197 -0
  246. package/templates/docker/src/lib/id.ts +29 -0
  247. package/templates/docker/src/lib/integrations/types.ts +166 -0
  248. package/templates/docker/src/lib/learn/pattern-analyzer.ts +224 -0
  249. package/templates/docker/src/lib/learn/pattern-cache.ts +229 -0
  250. package/templates/docker/src/lib/learn/pattern-proposer.ts +87 -0
  251. package/templates/docker/src/lib/learn/suggestion-helpers.ts +34 -0
  252. package/templates/docker/src/lib/learn/suggestions.ts +139 -0
  253. package/templates/docker/src/lib/linear/store.ts +200 -0
  254. package/templates/docker/src/lib/logger.ts +35 -3
  255. package/templates/docker/src/lib/metering.ts +272 -0
  256. package/templates/docker/src/lib/parsers.ts +99 -0
  257. package/templates/docker/src/lib/plugins/hooks.ts +13 -11
  258. package/templates/docker/src/lib/plugins/index.ts +3 -1
  259. package/templates/docker/src/lib/plugins/registry.ts +58 -6
  260. package/templates/docker/src/lib/plugins/settings.ts +147 -0
  261. package/templates/docker/src/lib/plugins/wiring.ts +6 -9
  262. package/templates/docker/src/lib/profiler.ts +1665 -0
  263. package/templates/docker/src/lib/providers.ts +188 -13
  264. package/templates/docker/src/lib/rls.ts +172 -60
  265. package/templates/docker/src/lib/sandbox/credentials.ts +206 -0
  266. package/templates/docker/src/lib/sandbox/validate.ts +179 -0
  267. package/templates/docker/src/lib/scheduled-task-types.ts +26 -94
  268. package/templates/docker/src/lib/scheduled-tasks.ts +174 -34
  269. package/templates/docker/src/lib/scheduler/delivery.ts +248 -150
  270. package/templates/docker/src/lib/scheduler/engine.ts +190 -154
  271. package/templates/docker/src/lib/scheduler/executor.ts +74 -23
  272. package/templates/docker/src/lib/scheduler/preview.ts +72 -0
  273. package/templates/docker/src/lib/security/abuse.ts +463 -0
  274. package/templates/docker/src/lib/semantic/diff.ts +267 -0
  275. package/templates/docker/src/lib/semantic/entities.ts +167 -0
  276. package/templates/docker/src/lib/semantic/files.ts +283 -0
  277. package/templates/docker/src/lib/semantic/index.ts +27 -0
  278. package/templates/docker/src/lib/{semantic-index.ts → semantic/search.ts} +80 -9
  279. package/templates/docker/src/lib/semantic/sync.ts +581 -0
  280. package/templates/docker/src/lib/{semantic.ts → semantic/whitelist.ts} +189 -3
  281. package/templates/docker/src/lib/settings.ts +817 -0
  282. package/templates/docker/src/lib/sidecar-types.ts +13 -0
  283. package/templates/docker/src/lib/slack/store.ts +134 -25
  284. package/templates/docker/src/lib/startup.ts +528 -362
  285. package/templates/docker/src/lib/teams/store.ts +216 -0
  286. package/templates/docker/src/lib/telegram/store.ts +202 -0
  287. package/templates/docker/src/lib/telemetry.ts +40 -0
  288. package/templates/docker/src/lib/tools/actions/audit.ts +8 -5
  289. package/templates/docker/src/lib/tools/actions/email.ts +3 -1
  290. package/templates/docker/src/lib/tools/actions/handler.ts +276 -93
  291. package/templates/docker/src/lib/tools/actions/jira.ts +2 -2
  292. package/templates/docker/src/lib/tools/backends/detect.ts +16 -0
  293. package/templates/docker/src/lib/tools/backends/index.ts +11 -0
  294. package/templates/docker/src/lib/tools/backends/nsjail.ts +213 -0
  295. package/templates/docker/src/lib/tools/backends/shared.ts +103 -0
  296. package/templates/docker/src/lib/tools/backends/types.ts +26 -0
  297. package/templates/docker/src/lib/tools/explore-nsjail.ts +7 -228
  298. package/templates/docker/src/lib/tools/explore-sandbox.ts +4 -29
  299. package/templates/docker/src/lib/tools/explore-sidecar.ts +18 -2
  300. package/templates/docker/src/lib/tools/explore.ts +246 -54
  301. package/templates/docker/src/lib/tools/index.ts +17 -0
  302. package/templates/docker/src/lib/tools/python-nsjail.ts +11 -139
  303. package/templates/docker/src/lib/tools/python-sandbox.ts +9 -132
  304. package/templates/docker/src/lib/tools/python-sidecar.ts +184 -3
  305. package/templates/docker/src/lib/tools/python-stream.ts +33 -0
  306. package/templates/docker/src/lib/tools/python-wrapper.ts +129 -0
  307. package/templates/docker/src/lib/tools/python.ts +115 -15
  308. package/templates/docker/src/lib/tools/registry.ts +14 -2
  309. package/templates/docker/src/lib/tools/sql.ts +778 -362
  310. package/templates/docker/src/lib/tracing.ts +16 -0
  311. package/templates/docker/src/lib/whatsapp/store.ts +198 -0
  312. package/templates/docker/src/lib/workspace.ts +89 -0
  313. package/templates/docker/src/progress.ts +121 -0
  314. package/templates/docker/src/types/data-table.ts +48 -0
  315. package/templates/docker/src/ui/atlas-chat-reexport.ts +3 -0
  316. package/templates/docker/src/ui/components/actions/action-approval-card.tsx +26 -19
  317. package/templates/docker/src/ui/components/actions/action-status-badge.tsx +3 -3
  318. package/templates/docker/src/ui/components/admin/admin-layout.tsx +57 -39
  319. package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +213 -35
  320. package/templates/docker/src/ui/components/admin/delivery-status-badge.tsx +53 -0
  321. package/templates/docker/src/ui/components/admin/empty-state.tsx +27 -6
  322. package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -52
  323. package/templates/docker/src/ui/components/admin/error-banner.tsx +2 -2
  324. package/templates/docker/src/ui/components/admin/feature-disabled.tsx +28 -5
  325. package/templates/docker/src/ui/components/admin-content-wrapper.tsx +87 -0
  326. package/templates/docker/src/ui/components/atlas-chat.tsx +449 -166
  327. package/templates/docker/src/ui/components/branding-head.tsx +41 -0
  328. package/templates/docker/src/ui/components/chart/chart-detection.ts +62 -5
  329. package/templates/docker/src/ui/components/chart/result-chart.tsx +316 -125
  330. package/templates/docker/src/ui/components/chat/api-key-bar.tsx +4 -4
  331. package/templates/docker/src/ui/components/chat/data-table.tsx +45 -4
  332. package/templates/docker/src/ui/components/chat/error-banner.tsx +86 -5
  333. package/templates/docker/src/ui/components/chat/follow-up-chips.tsx +29 -0
  334. package/templates/docker/src/ui/components/chat/markdown.tsx +24 -0
  335. package/templates/docker/src/ui/components/chat/prompt-library.tsx +206 -0
  336. package/templates/docker/src/ui/components/chat/python-result-card.tsx +106 -78
  337. package/templates/docker/src/ui/components/chat/result-card-base.tsx +101 -0
  338. package/templates/docker/src/ui/components/chat/share-dialog.tsx +377 -0
  339. package/templates/docker/src/ui/components/chat/sql-result-card.tsx +94 -73
  340. package/templates/docker/src/ui/components/chat/suggestion-chips.tsx +46 -0
  341. package/templates/docker/src/ui/components/chat/tool-part.tsx +16 -4
  342. package/templates/docker/src/ui/components/conversations/conversation-item.tsx +48 -17
  343. package/templates/docker/src/ui/components/conversations/conversation-list.tsx +38 -24
  344. package/templates/docker/src/ui/components/conversations/conversation-sidebar.tsx +66 -7
  345. package/templates/docker/src/ui/components/conversations/delete-confirmation.tsx +9 -2
  346. package/templates/docker/src/ui/components/error-boundary.tsx +66 -0
  347. package/templates/docker/src/ui/components/notebook/delete-cell-dialog.tsx +48 -0
  348. package/templates/docker/src/ui/components/notebook/fork-branch-selector.tsx +68 -0
  349. package/templates/docker/src/ui/components/notebook/notebook-cell-input.tsx +76 -0
  350. package/templates/docker/src/ui/components/notebook/notebook-cell-output.tsx +58 -0
  351. package/templates/docker/src/ui/components/notebook/notebook-cell-toolbar.tsx +91 -0
  352. package/templates/docker/src/ui/components/notebook/notebook-cell.tsx +119 -0
  353. package/templates/docker/src/ui/components/notebook/notebook-empty-state.tsx +19 -0
  354. package/templates/docker/src/ui/components/notebook/notebook-export.ts +287 -0
  355. package/templates/docker/src/ui/components/notebook/notebook-input-bar.tsx +49 -0
  356. package/templates/docker/src/ui/components/notebook/notebook-shell.tsx +266 -0
  357. package/templates/docker/src/ui/components/notebook/notebook-text-cell.tsx +152 -0
  358. package/templates/docker/src/ui/components/notebook/types.ts +39 -0
  359. package/templates/docker/src/ui/components/notebook/use-keyboard-nav.ts +109 -0
  360. package/templates/docker/src/ui/components/notebook/use-notebook.ts +684 -0
  361. package/templates/docker/src/ui/components/org-switcher.tsx +111 -0
  362. package/templates/docker/src/ui/components/region-picker.tsx +103 -0
  363. package/templates/docker/src/ui/components/schema-explorer/schema-explorer.tsx +522 -0
  364. package/templates/docker/src/ui/components/social-icons.tsx +26 -0
  365. package/templates/docker/src/ui/components/tour/guided-tour.tsx +81 -0
  366. package/templates/docker/src/ui/components/tour/index.ts +5 -0
  367. package/templates/docker/src/ui/components/tour/nav-bar.tsx +100 -0
  368. package/templates/docker/src/ui/components/tour/tour-overlay.tsx +298 -0
  369. package/templates/docker/src/ui/components/tour/tour-steps.ts +43 -0
  370. package/templates/docker/src/ui/components/tour/types.ts +21 -0
  371. package/templates/docker/src/ui/components/tour/use-tour.ts +193 -0
  372. package/templates/docker/src/ui/context-reexport.ts +3 -0
  373. package/templates/docker/src/ui/hooks/theme-init-script.ts +17 -0
  374. package/templates/docker/src/ui/hooks/use-admin-fetch.ts +38 -30
  375. package/templates/docker/src/ui/hooks/use-admin-mutation.ts +188 -0
  376. package/templates/docker/src/ui/hooks/use-atlas-transport.ts +225 -0
  377. package/templates/docker/src/ui/hooks/use-branding.ts +68 -0
  378. package/templates/docker/src/ui/hooks/use-conversations.ts +106 -83
  379. package/templates/docker/src/ui/hooks/use-dark-mode.ts +134 -10
  380. package/templates/docker/src/ui/hooks/use-deploy-mode.ts +36 -0
  381. package/templates/docker/src/ui/hooks/use-platform-admin-guard.ts +49 -0
  382. package/templates/docker/src/ui/lib/action-types.ts +11 -63
  383. package/templates/docker/src/ui/lib/admin-schemas.ts +744 -0
  384. package/templates/docker/src/ui/lib/fetch-client.ts +84 -0
  385. package/templates/docker/src/ui/lib/fetch-error.ts +54 -0
  386. package/templates/docker/src/ui/lib/helpers.ts +94 -1
  387. package/templates/docker/src/ui/lib/types.ts +149 -140
  388. package/templates/docker/tsconfig.json +4 -2
  389. package/templates/nextjs-standalone/bin/__tests__/duckdb-ingest.test.ts +17 -14
  390. package/templates/nextjs-standalone/bin/__tests__/failure-threshold.test.ts +148 -0
  391. package/templates/nextjs-standalone/bin/__tests__/fatal-error-propagation.test.ts +267 -0
  392. package/templates/nextjs-standalone/bin/__tests__/profiler-heuristics.test.ts +5 -5
  393. package/templates/nextjs-standalone/bin/__tests__/schema-drift.test.ts +39 -0
  394. package/templates/nextjs-standalone/bin/atlas.ts +981 -1819
  395. package/templates/nextjs-standalone/bin/benchmark.ts +14 -16
  396. package/templates/nextjs-standalone/bin/enrich.ts +7 -2
  397. package/templates/nextjs-standalone/brand.css +13 -0
  398. package/templates/nextjs-standalone/data/cybersec-semantic/catalog.yml +222 -0
  399. package/templates/nextjs-standalone/data/cybersec-semantic/entities/alerts.yml +195 -0
  400. package/templates/nextjs-standalone/data/cybersec-semantic/entities/assets.yml +191 -0
  401. package/templates/nextjs-standalone/data/cybersec-semantic/entities/compliance_assessments.yml +170 -0
  402. package/templates/nextjs-standalone/data/cybersec-semantic/entities/incidents.yml +219 -0
  403. package/templates/nextjs-standalone/data/cybersec-semantic/entities/organizations.yml +136 -0
  404. package/templates/nextjs-standalone/data/cybersec-semantic/entities/plans.yml +114 -0
  405. package/templates/nextjs-standalone/data/cybersec-semantic/entities/remediation_actions.yml +212 -0
  406. package/templates/nextjs-standalone/data/cybersec-semantic/entities/scan_results.yml +215 -0
  407. package/templates/nextjs-standalone/data/cybersec-semantic/entities/scans.yml +180 -0
  408. package/templates/nextjs-standalone/data/cybersec-semantic/entities/subscriptions.yml +184 -0
  409. package/templates/nextjs-standalone/data/cybersec-semantic/entities/users.yml +140 -0
  410. package/templates/nextjs-standalone/data/cybersec-semantic/entities/vulnerabilities.yml +154 -0
  411. package/templates/nextjs-standalone/data/cybersec-semantic/glossary.yml +207 -0
  412. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/business.yml +148 -0
  413. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/compliance.yml +138 -0
  414. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/security.yml +181 -0
  415. package/templates/nextjs-standalone/data/cybersec.sql +8 -8
  416. package/templates/nextjs-standalone/data/demo.sql +3 -0
  417. package/templates/nextjs-standalone/data/ecommerce-semantic/catalog.yml +221 -0
  418. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/categories.yml +91 -0
  419. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/customers.yml +133 -0
  420. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/email_campaigns.yml +119 -0
  421. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/inventory_levels.yml +153 -0
  422. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/order_items.yml +159 -0
  423. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/orders.yml +199 -0
  424. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/payments.yml +140 -0
  425. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/product_reviews.yml +155 -0
  426. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/products.yml +178 -0
  427. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/promotions.yml +171 -0
  428. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/returns.yml +144 -0
  429. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/sellers.yml +124 -0
  430. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/shipments.yml +159 -0
  431. package/templates/nextjs-standalone/data/ecommerce-semantic/glossary.yml +193 -0
  432. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/customers.yml +116 -0
  433. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/operations.yml +131 -0
  434. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/revenue.yml +120 -0
  435. package/templates/nextjs-standalone/docs/deploy.md +2 -1
  436. package/templates/nextjs-standalone/ee/src/__mocks__/internal.ts +170 -0
  437. package/templates/nextjs-standalone/ee/src/audit/purge-scheduler.ts +113 -0
  438. package/templates/nextjs-standalone/ee/src/audit/retention.ts +467 -0
  439. package/templates/nextjs-standalone/ee/src/auth/ip-allowlist.ts +367 -0
  440. package/templates/nextjs-standalone/ee/src/auth/roles.ts +562 -0
  441. package/templates/nextjs-standalone/ee/src/auth/scim.ts +343 -0
  442. package/templates/nextjs-standalone/ee/src/auth/sso.ts +538 -0
  443. package/templates/nextjs-standalone/ee/src/backups/engine.ts +355 -0
  444. package/templates/nextjs-standalone/ee/src/backups/index.ts +26 -0
  445. package/templates/nextjs-standalone/ee/src/backups/restore.ts +169 -0
  446. package/templates/nextjs-standalone/ee/src/backups/scheduler.ts +153 -0
  447. package/templates/nextjs-standalone/ee/src/backups/verify.ts +124 -0
  448. package/templates/nextjs-standalone/ee/src/branding/white-label.ts +228 -0
  449. package/templates/nextjs-standalone/ee/src/compliance/masking.ts +477 -0
  450. package/templates/nextjs-standalone/ee/src/compliance/patterns.ts +16 -0
  451. package/templates/nextjs-standalone/ee/src/compliance/pii-detection.ts +217 -0
  452. package/templates/nextjs-standalone/ee/src/compliance/reports.ts +402 -0
  453. package/templates/nextjs-standalone/ee/src/deploy-mode.ts +37 -0
  454. package/templates/nextjs-standalone/ee/src/governance/approval.ts +699 -0
  455. package/templates/nextjs-standalone/ee/src/index.ts +74 -0
  456. package/templates/nextjs-standalone/ee/src/platform/domains.ts +562 -0
  457. package/templates/nextjs-standalone/ee/src/platform/model-routing.ts +382 -0
  458. package/templates/nextjs-standalone/ee/src/platform/residency.ts +265 -0
  459. package/templates/nextjs-standalone/ee/src/sla/alerting.ts +382 -0
  460. package/templates/nextjs-standalone/ee/src/sla/index.ts +12 -0
  461. package/templates/nextjs-standalone/ee/src/sla/metrics.ts +275 -0
  462. package/templates/nextjs-standalone/ee/src/test-setup.ts +1 -0
  463. package/templates/nextjs-standalone/next.config.ts +1 -1
  464. package/templates/nextjs-standalone/package.json +50 -30
  465. package/templates/nextjs-standalone/src/api/index.ts +336 -24
  466. package/templates/nextjs-standalone/src/api/routes/actions.ts +443 -176
  467. package/templates/nextjs-standalone/src/api/routes/admin-abuse.ts +219 -0
  468. package/templates/nextjs-standalone/src/api/routes/admin-approval.ts +418 -0
  469. package/templates/nextjs-standalone/src/api/routes/admin-audit-retention.ts +405 -0
  470. package/templates/nextjs-standalone/src/api/routes/admin-auth.ts +122 -0
  471. package/templates/nextjs-standalone/src/api/routes/admin-branding.ts +252 -0
  472. package/templates/nextjs-standalone/src/api/routes/admin-compliance.ts +352 -0
  473. package/templates/nextjs-standalone/src/api/routes/admin-domains.ts +334 -0
  474. package/templates/nextjs-standalone/src/api/routes/admin-integrations.ts +2667 -0
  475. package/templates/nextjs-standalone/src/api/routes/admin-ip-allowlist.ts +261 -0
  476. package/templates/nextjs-standalone/src/api/routes/admin-learned-patterns.ts +525 -0
  477. package/templates/nextjs-standalone/src/api/routes/admin-model-config.ts +252 -0
  478. package/templates/nextjs-standalone/src/api/routes/admin-onboarding-emails.ts +145 -0
  479. package/templates/nextjs-standalone/src/api/routes/admin-orgs.ts +710 -0
  480. package/templates/nextjs-standalone/src/api/routes/admin-prompts.ts +694 -0
  481. package/templates/nextjs-standalone/src/api/routes/admin-residency.ts +570 -0
  482. package/templates/nextjs-standalone/src/api/routes/admin-roles.ts +296 -0
  483. package/templates/nextjs-standalone/src/api/routes/admin-router.ts +120 -0
  484. package/templates/nextjs-standalone/src/api/routes/admin-sandbox.ts +417 -0
  485. package/templates/nextjs-standalone/src/api/routes/admin-scim.ts +262 -0
  486. package/templates/nextjs-standalone/src/api/routes/admin-sso.ts +545 -0
  487. package/templates/nextjs-standalone/src/api/routes/admin-suggestions.ts +176 -0
  488. package/templates/nextjs-standalone/src/api/routes/admin-usage.ts +310 -0
  489. package/templates/nextjs-standalone/src/api/routes/admin.ts +4156 -898
  490. package/templates/nextjs-standalone/src/api/routes/auth-preamble.ts +105 -0
  491. package/templates/nextjs-standalone/src/api/routes/billing.ts +397 -0
  492. package/templates/nextjs-standalone/src/api/routes/chat.ts +597 -334
  493. package/templates/nextjs-standalone/src/api/routes/conversations.ts +987 -132
  494. package/templates/nextjs-standalone/src/api/routes/demo.ts +673 -0
  495. package/templates/nextjs-standalone/src/api/routes/discord.ts +274 -0
  496. package/templates/nextjs-standalone/src/api/routes/ee-error-handler.ts +32 -0
  497. package/templates/nextjs-standalone/src/api/routes/health.ts +129 -14
  498. package/templates/nextjs-standalone/src/api/routes/middleware.ts +244 -0
  499. package/templates/nextjs-standalone/src/api/routes/onboarding-emails.ts +134 -0
  500. package/templates/nextjs-standalone/src/api/routes/onboarding.ts +1109 -0
  501. package/templates/nextjs-standalone/src/api/routes/openapi.ts +184 -1597
  502. package/templates/nextjs-standalone/src/api/routes/platform-admin.ts +760 -0
  503. package/templates/nextjs-standalone/src/api/routes/platform-backups.ts +436 -0
  504. package/templates/nextjs-standalone/src/api/routes/platform-domains.ts +235 -0
  505. package/templates/nextjs-standalone/src/api/routes/platform-residency.ts +257 -0
  506. package/templates/nextjs-standalone/src/api/routes/platform-sla.ts +379 -0
  507. package/templates/nextjs-standalone/src/api/routes/prompts.ts +221 -0
  508. package/templates/nextjs-standalone/src/api/routes/public-branding.ts +106 -0
  509. package/templates/nextjs-standalone/src/api/routes/query.ts +330 -219
  510. package/templates/nextjs-standalone/src/api/routes/scheduled-tasks.ts +393 -297
  511. package/templates/nextjs-standalone/src/api/routes/semantic.ts +179 -0
  512. package/templates/nextjs-standalone/src/api/routes/sessions.ts +210 -0
  513. package/templates/nextjs-standalone/src/api/routes/shared-domains.ts +98 -0
  514. package/templates/nextjs-standalone/src/api/routes/shared-schemas.ts +139 -0
  515. package/templates/nextjs-standalone/src/api/routes/slack.ts +209 -52
  516. package/templates/nextjs-standalone/src/api/routes/suggestions.ts +233 -0
  517. package/templates/nextjs-standalone/src/api/routes/tables.ts +67 -0
  518. package/templates/nextjs-standalone/src/api/routes/teams.ts +222 -0
  519. package/templates/nextjs-standalone/src/api/routes/validate-sql.ts +188 -0
  520. package/templates/nextjs-standalone/src/api/routes/validation-hook.ts +62 -0
  521. package/templates/nextjs-standalone/src/api/routes/widget-loader.ts +356 -0
  522. package/templates/nextjs-standalone/src/api/routes/widget.ts +428 -0
  523. package/templates/nextjs-standalone/src/api/routes/wizard.ts +852 -0
  524. package/templates/nextjs-standalone/src/api/server.ts +187 -69
  525. package/templates/nextjs-standalone/src/app/error.tsx +5 -2
  526. package/templates/nextjs-standalone/src/app/globals.css +1 -1
  527. package/templates/nextjs-standalone/src/app/layout.tsx +7 -2
  528. package/templates/nextjs-standalone/src/app/page.tsx +39 -5
  529. package/templates/nextjs-standalone/src/components/data-table/data-table-column-header.tsx +99 -0
  530. package/templates/nextjs-standalone/src/components/data-table/data-table-date-filter.tsx +225 -0
  531. package/templates/nextjs-standalone/src/components/data-table/data-table-expandable.tsx +125 -0
  532. package/templates/nextjs-standalone/src/components/data-table/data-table-faceted-filter.tsx +189 -0
  533. package/templates/nextjs-standalone/src/components/data-table/data-table-pagination.tsx +112 -0
  534. package/templates/nextjs-standalone/src/components/data-table/data-table-range-filter.tsx +122 -0
  535. package/templates/nextjs-standalone/src/components/data-table/data-table-slider-filter.tsx +256 -0
  536. package/templates/nextjs-standalone/src/components/data-table/data-table-sort-list.tsx +407 -0
  537. package/templates/nextjs-standalone/src/components/data-table/data-table-toolbar.tsx +149 -0
  538. package/templates/nextjs-standalone/src/components/data-table/data-table-view-options.tsx +89 -0
  539. package/templates/nextjs-standalone/src/components/data-table/data-table.tsx +105 -0
  540. package/templates/nextjs-standalone/src/components/form-dialog.tsx +135 -0
  541. package/templates/nextjs-standalone/src/components/ui/accordion.tsx +66 -0
  542. package/templates/nextjs-standalone/src/components/ui/calendar.tsx +220 -0
  543. package/templates/nextjs-standalone/src/components/ui/checkbox.tsx +32 -0
  544. package/templates/nextjs-standalone/src/components/ui/faceted.tsx +283 -0
  545. package/templates/nextjs-standalone/src/components/ui/form.tsx +167 -0
  546. package/templates/nextjs-standalone/src/components/ui/label.tsx +24 -0
  547. package/templates/nextjs-standalone/src/components/ui/popover.tsx +89 -0
  548. package/templates/nextjs-standalone/src/components/ui/progress.tsx +31 -0
  549. package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +6 -2
  550. package/templates/nextjs-standalone/src/components/ui/slider.tsx +63 -0
  551. package/templates/nextjs-standalone/src/components/ui/sortable.tsx +581 -0
  552. package/templates/nextjs-standalone/src/components/ui/switch.tsx +35 -0
  553. package/templates/nextjs-standalone/src/components/ui/textarea.tsx +18 -0
  554. package/templates/nextjs-standalone/src/config/data-table.ts +82 -0
  555. package/templates/nextjs-standalone/src/env-check.ts +74 -0
  556. package/templates/nextjs-standalone/src/hooks/use-callback-ref.ts +27 -0
  557. package/templates/nextjs-standalone/src/hooks/use-data-table.ts +316 -0
  558. package/templates/nextjs-standalone/src/hooks/use-debounced-callback.ts +28 -0
  559. package/templates/nextjs-standalone/src/lib/action-types.ts +7 -41
  560. package/templates/nextjs-standalone/src/lib/agent-query.ts +4 -2
  561. package/templates/nextjs-standalone/src/lib/agent.ts +363 -31
  562. package/templates/nextjs-standalone/src/lib/api-url.ts +2 -3
  563. package/templates/nextjs-standalone/src/lib/auth/admin-permissions.ts +38 -0
  564. package/templates/nextjs-standalone/src/lib/auth/audit.ts +19 -4
  565. package/templates/nextjs-standalone/src/lib/auth/byot.ts +3 -3
  566. package/templates/nextjs-standalone/src/lib/auth/detect.ts +29 -8
  567. package/templates/nextjs-standalone/src/lib/auth/managed.ts +104 -14
  568. package/templates/nextjs-standalone/src/lib/auth/middleware.ts +53 -6
  569. package/templates/nextjs-standalone/src/lib/auth/migrate.ts +140 -15
  570. package/templates/nextjs-standalone/src/lib/auth/oauth-state.ts +123 -0
  571. package/templates/nextjs-standalone/src/lib/auth/org-permissions.ts +55 -0
  572. package/templates/nextjs-standalone/src/lib/auth/permissions.ts +26 -19
  573. package/templates/nextjs-standalone/src/lib/auth/server.ts +355 -9
  574. package/templates/nextjs-standalone/src/lib/auth/simple-key.ts +3 -3
  575. package/templates/nextjs-standalone/src/lib/auth/types.ts +15 -21
  576. package/templates/nextjs-standalone/src/lib/billing/enforcement.ts +368 -0
  577. package/templates/nextjs-standalone/src/lib/billing/plans.ts +155 -0
  578. package/templates/nextjs-standalone/src/lib/cache/index.ts +92 -0
  579. package/templates/nextjs-standalone/src/lib/cache/keys.ts +30 -0
  580. package/templates/nextjs-standalone/src/lib/cache/lru.ts +79 -0
  581. package/templates/nextjs-standalone/src/lib/cache/types.ts +31 -0
  582. package/templates/nextjs-standalone/src/lib/compose-refs.ts +62 -0
  583. package/templates/nextjs-standalone/src/lib/config.ts +563 -11
  584. package/templates/nextjs-standalone/src/lib/connection-types.ts +9 -0
  585. package/templates/nextjs-standalone/src/lib/conversation-types.ts +1 -25
  586. package/templates/nextjs-standalone/src/lib/conversations.ts +345 -14
  587. package/templates/nextjs-standalone/src/lib/data-table.ts +61 -0
  588. package/templates/nextjs-standalone/src/lib/db/connection.ts +793 -39
  589. package/templates/nextjs-standalone/src/lib/db/internal.ts +985 -139
  590. package/templates/nextjs-standalone/src/lib/db/migrate.ts +295 -0
  591. package/templates/nextjs-standalone/src/lib/db/migrations/0000_baseline.sql +703 -0
  592. package/templates/nextjs-standalone/src/lib/db/migrations/0001_teams_installations.sql +14 -0
  593. package/templates/nextjs-standalone/src/lib/db/migrations/0002_discord_installations.sql +14 -0
  594. package/templates/nextjs-standalone/src/lib/db/migrations/0003_telegram_installations.sql +15 -0
  595. package/templates/nextjs-standalone/src/lib/db/migrations/0004_sandbox_credentials.sql +18 -0
  596. package/templates/nextjs-standalone/src/lib/db/migrations/0005_oauth_state.sql +16 -0
  597. package/templates/nextjs-standalone/src/lib/db/migrations/0006_byot_credentials.sql +14 -0
  598. package/templates/nextjs-standalone/src/lib/db/migrations/0007_gchat_installations.sql +15 -0
  599. package/templates/nextjs-standalone/src/lib/db/migrations/0008_github_installations.sql +14 -0
  600. package/templates/nextjs-standalone/src/lib/db/migrations/0009_linear_installations.sql +15 -0
  601. package/templates/nextjs-standalone/src/lib/db/migrations/0010_whatsapp_installations.sql +14 -0
  602. package/templates/nextjs-standalone/src/lib/db/migrations/0011_email_installations.sql +16 -0
  603. package/templates/nextjs-standalone/src/lib/db/migrations/0012_region_migrations.sql +25 -0
  604. package/templates/nextjs-standalone/src/lib/db/schema.ts +1120 -0
  605. package/templates/nextjs-standalone/src/lib/db/source-rate-limit.ts +89 -139
  606. package/templates/nextjs-standalone/src/lib/demo.ts +308 -0
  607. package/templates/nextjs-standalone/src/lib/discord/store.ts +225 -0
  608. package/templates/nextjs-standalone/src/lib/effect/ai.ts +243 -0
  609. package/templates/nextjs-standalone/src/lib/effect/errors.ts +234 -0
  610. package/templates/nextjs-standalone/src/lib/effect/hono.ts +454 -0
  611. package/templates/nextjs-standalone/src/lib/effect/index.ts +137 -0
  612. package/templates/nextjs-standalone/src/lib/effect/layers.ts +496 -0
  613. package/templates/nextjs-standalone/src/lib/effect/services.ts +776 -0
  614. package/templates/nextjs-standalone/src/lib/effect/sql.ts +178 -0
  615. package/templates/nextjs-standalone/src/lib/effect/toolkit.ts +123 -0
  616. package/templates/nextjs-standalone/src/lib/email/delivery.ts +232 -0
  617. package/templates/nextjs-standalone/src/lib/email/engine.ts +349 -0
  618. package/templates/nextjs-standalone/src/lib/email/hooks.ts +107 -0
  619. package/templates/nextjs-standalone/src/lib/email/index.ts +16 -0
  620. package/templates/nextjs-standalone/src/lib/email/scheduler.ts +72 -0
  621. package/templates/nextjs-standalone/src/lib/email/sequence.ts +73 -0
  622. package/templates/nextjs-standalone/src/lib/email/store.ts +163 -0
  623. package/templates/nextjs-standalone/src/lib/email/templates.ts +215 -0
  624. package/templates/nextjs-standalone/src/lib/format.test.ts +117 -0
  625. package/templates/nextjs-standalone/src/lib/format.ts +67 -0
  626. package/templates/nextjs-standalone/src/lib/gchat/store.ts +202 -0
  627. package/templates/nextjs-standalone/src/lib/github/store.ts +197 -0
  628. package/templates/nextjs-standalone/src/lib/id.ts +29 -0
  629. package/templates/nextjs-standalone/src/lib/integrations/types.ts +166 -0
  630. package/templates/nextjs-standalone/src/lib/learn/pattern-analyzer.ts +224 -0
  631. package/templates/nextjs-standalone/src/lib/learn/pattern-cache.ts +229 -0
  632. package/templates/nextjs-standalone/src/lib/learn/pattern-proposer.ts +87 -0
  633. package/templates/nextjs-standalone/src/lib/learn/suggestion-helpers.ts +34 -0
  634. package/templates/nextjs-standalone/src/lib/learn/suggestions.ts +139 -0
  635. package/templates/nextjs-standalone/src/lib/linear/store.ts +200 -0
  636. package/templates/nextjs-standalone/src/lib/logger.ts +35 -3
  637. package/templates/nextjs-standalone/src/lib/metering.ts +272 -0
  638. package/templates/nextjs-standalone/src/lib/parsers.ts +99 -0
  639. package/templates/nextjs-standalone/src/lib/plugins/hooks.ts +13 -11
  640. package/templates/nextjs-standalone/src/lib/plugins/index.ts +3 -1
  641. package/templates/nextjs-standalone/src/lib/plugins/registry.ts +58 -6
  642. package/templates/nextjs-standalone/src/lib/plugins/settings.ts +147 -0
  643. package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +6 -9
  644. package/templates/nextjs-standalone/src/lib/profiler.ts +1665 -0
  645. package/templates/nextjs-standalone/src/lib/providers.ts +188 -13
  646. package/templates/nextjs-standalone/src/lib/rls.ts +172 -60
  647. package/templates/nextjs-standalone/src/lib/sandbox/credentials.ts +206 -0
  648. package/templates/nextjs-standalone/src/lib/sandbox/validate.ts +179 -0
  649. package/templates/nextjs-standalone/src/lib/scheduled-task-types.ts +26 -94
  650. package/templates/nextjs-standalone/src/lib/scheduled-tasks.ts +174 -34
  651. package/templates/nextjs-standalone/src/lib/scheduler/delivery.ts +248 -150
  652. package/templates/nextjs-standalone/src/lib/scheduler/engine.ts +190 -154
  653. package/templates/nextjs-standalone/src/lib/scheduler/executor.ts +74 -23
  654. package/templates/nextjs-standalone/src/lib/scheduler/preview.ts +72 -0
  655. package/templates/nextjs-standalone/src/lib/security/abuse.ts +463 -0
  656. package/templates/nextjs-standalone/src/lib/semantic/diff.ts +267 -0
  657. package/templates/nextjs-standalone/src/lib/semantic/entities.ts +167 -0
  658. package/templates/nextjs-standalone/src/lib/semantic/files.ts +283 -0
  659. package/templates/nextjs-standalone/src/lib/semantic/index.ts +27 -0
  660. package/templates/nextjs-standalone/src/lib/{semantic-index.ts → semantic/search.ts} +80 -9
  661. package/templates/nextjs-standalone/src/lib/semantic/sync.ts +581 -0
  662. package/templates/nextjs-standalone/src/lib/{semantic.ts → semantic/whitelist.ts} +189 -3
  663. package/templates/nextjs-standalone/src/lib/settings.ts +817 -0
  664. package/templates/nextjs-standalone/src/lib/sidecar-types.ts +13 -0
  665. package/templates/nextjs-standalone/src/lib/slack/store.ts +134 -25
  666. package/templates/nextjs-standalone/src/lib/startup.ts +528 -362
  667. package/templates/nextjs-standalone/src/lib/teams/store.ts +216 -0
  668. package/templates/nextjs-standalone/src/lib/telegram/store.ts +202 -0
  669. package/templates/nextjs-standalone/src/lib/telemetry.ts +40 -0
  670. package/templates/nextjs-standalone/src/lib/tools/actions/audit.ts +8 -5
  671. package/templates/nextjs-standalone/src/lib/tools/actions/email.ts +3 -1
  672. package/templates/nextjs-standalone/src/lib/tools/actions/handler.ts +276 -93
  673. package/templates/nextjs-standalone/src/lib/tools/actions/jira.ts +2 -2
  674. package/templates/nextjs-standalone/src/lib/tools/backends/detect.ts +16 -0
  675. package/templates/nextjs-standalone/src/lib/tools/backends/index.ts +11 -0
  676. package/templates/nextjs-standalone/src/lib/tools/backends/nsjail.ts +213 -0
  677. package/templates/nextjs-standalone/src/lib/tools/backends/shared.ts +103 -0
  678. package/templates/nextjs-standalone/src/lib/tools/backends/types.ts +26 -0
  679. package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +7 -228
  680. package/templates/nextjs-standalone/src/lib/tools/explore-sandbox.ts +4 -29
  681. package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +18 -2
  682. package/templates/nextjs-standalone/src/lib/tools/explore.ts +246 -54
  683. package/templates/nextjs-standalone/src/lib/tools/index.ts +17 -0
  684. package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +11 -139
  685. package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +9 -132
  686. package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +184 -3
  687. package/templates/nextjs-standalone/src/lib/tools/python-stream.ts +33 -0
  688. package/templates/nextjs-standalone/src/lib/tools/python-wrapper.ts +129 -0
  689. package/templates/nextjs-standalone/src/lib/tools/python.ts +115 -15
  690. package/templates/nextjs-standalone/src/lib/tools/registry.ts +14 -2
  691. package/templates/nextjs-standalone/src/lib/tools/sql.ts +778 -362
  692. package/templates/nextjs-standalone/src/lib/tracing.ts +16 -0
  693. package/templates/nextjs-standalone/src/lib/whatsapp/store.ts +198 -0
  694. package/templates/nextjs-standalone/src/lib/workspace.ts +89 -0
  695. package/templates/nextjs-standalone/src/progress.ts +121 -0
  696. package/templates/nextjs-standalone/src/types/data-table.ts +48 -0
  697. package/templates/nextjs-standalone/src/ui/atlas-chat-reexport.ts +3 -0
  698. package/templates/nextjs-standalone/src/ui/components/actions/action-approval-card.tsx +26 -19
  699. package/templates/nextjs-standalone/src/ui/components/actions/action-status-badge.tsx +3 -3
  700. package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +57 -39
  701. package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +213 -35
  702. package/templates/nextjs-standalone/src/ui/components/admin/delivery-status-badge.tsx +53 -0
  703. package/templates/nextjs-standalone/src/ui/components/admin/empty-state.tsx +27 -6
  704. package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -52
  705. package/templates/nextjs-standalone/src/ui/components/admin/error-banner.tsx +2 -2
  706. package/templates/nextjs-standalone/src/ui/components/admin/feature-disabled.tsx +28 -5
  707. package/templates/nextjs-standalone/src/ui/components/admin-content-wrapper.tsx +87 -0
  708. package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +449 -166
  709. package/templates/nextjs-standalone/src/ui/components/branding-head.tsx +41 -0
  710. package/templates/nextjs-standalone/src/ui/components/chart/chart-detection.ts +62 -5
  711. package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +316 -125
  712. package/templates/nextjs-standalone/src/ui/components/chat/api-key-bar.tsx +4 -4
  713. package/templates/nextjs-standalone/src/ui/components/chat/data-table.tsx +45 -4
  714. package/templates/nextjs-standalone/src/ui/components/chat/error-banner.tsx +86 -5
  715. package/templates/nextjs-standalone/src/ui/components/chat/follow-up-chips.tsx +29 -0
  716. package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +24 -0
  717. package/templates/nextjs-standalone/src/ui/components/chat/prompt-library.tsx +206 -0
  718. package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +106 -78
  719. package/templates/nextjs-standalone/src/ui/components/chat/result-card-base.tsx +101 -0
  720. package/templates/nextjs-standalone/src/ui/components/chat/share-dialog.tsx +377 -0
  721. package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +94 -73
  722. package/templates/nextjs-standalone/src/ui/components/chat/suggestion-chips.tsx +46 -0
  723. package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +16 -4
  724. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +48 -17
  725. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-list.tsx +38 -24
  726. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-sidebar.tsx +66 -7
  727. package/templates/nextjs-standalone/src/ui/components/conversations/delete-confirmation.tsx +9 -2
  728. package/templates/nextjs-standalone/src/ui/components/error-boundary.tsx +66 -0
  729. package/templates/nextjs-standalone/src/ui/components/notebook/delete-cell-dialog.tsx +48 -0
  730. package/templates/nextjs-standalone/src/ui/components/notebook/fork-branch-selector.tsx +68 -0
  731. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-input.tsx +76 -0
  732. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-output.tsx +58 -0
  733. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-toolbar.tsx +91 -0
  734. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell.tsx +119 -0
  735. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-empty-state.tsx +19 -0
  736. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-export.ts +287 -0
  737. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-input-bar.tsx +49 -0
  738. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-shell.tsx +266 -0
  739. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-text-cell.tsx +152 -0
  740. package/templates/nextjs-standalone/src/ui/components/notebook/types.ts +39 -0
  741. package/templates/nextjs-standalone/src/ui/components/notebook/use-keyboard-nav.ts +109 -0
  742. package/templates/nextjs-standalone/src/ui/components/notebook/use-notebook.ts +684 -0
  743. package/templates/nextjs-standalone/src/ui/components/org-switcher.tsx +111 -0
  744. package/templates/nextjs-standalone/src/ui/components/region-picker.tsx +103 -0
  745. package/templates/nextjs-standalone/src/ui/components/schema-explorer/schema-explorer.tsx +522 -0
  746. package/templates/nextjs-standalone/src/ui/components/social-icons.tsx +26 -0
  747. package/templates/nextjs-standalone/src/ui/components/tour/guided-tour.tsx +81 -0
  748. package/templates/nextjs-standalone/src/ui/components/tour/index.ts +5 -0
  749. package/templates/nextjs-standalone/src/ui/components/tour/nav-bar.tsx +100 -0
  750. package/templates/nextjs-standalone/src/ui/components/tour/tour-overlay.tsx +298 -0
  751. package/templates/nextjs-standalone/src/ui/components/tour/tour-steps.ts +43 -0
  752. package/templates/nextjs-standalone/src/ui/components/tour/types.ts +21 -0
  753. package/templates/nextjs-standalone/src/ui/components/tour/use-tour.ts +193 -0
  754. package/templates/nextjs-standalone/src/ui/context-reexport.ts +3 -0
  755. package/templates/nextjs-standalone/src/ui/hooks/theme-init-script.ts +17 -0
  756. package/templates/nextjs-standalone/src/ui/hooks/use-admin-fetch.ts +38 -30
  757. package/templates/nextjs-standalone/src/ui/hooks/use-admin-mutation.ts +188 -0
  758. package/templates/nextjs-standalone/src/ui/hooks/use-atlas-transport.ts +225 -0
  759. package/templates/nextjs-standalone/src/ui/hooks/use-branding.ts +68 -0
  760. package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +106 -83
  761. package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +134 -10
  762. package/templates/nextjs-standalone/src/ui/hooks/use-deploy-mode.ts +36 -0
  763. package/templates/nextjs-standalone/src/ui/hooks/use-platform-admin-guard.ts +49 -0
  764. package/templates/nextjs-standalone/src/ui/lib/action-types.ts +11 -63
  765. package/templates/nextjs-standalone/src/ui/lib/admin-schemas.ts +744 -0
  766. package/templates/nextjs-standalone/src/ui/lib/fetch-client.ts +84 -0
  767. package/templates/nextjs-standalone/src/ui/lib/fetch-error.ts +54 -0
  768. package/templates/nextjs-standalone/src/ui/lib/helpers.ts +94 -1
  769. package/templates/nextjs-standalone/src/ui/lib/types.ts +149 -140
  770. package/templates/nextjs-standalone/tsconfig.json +3 -2
  771. package/templates/docker/src/api/__tests__/actions.test.ts +0 -683
  772. package/templates/docker/src/api/__tests__/admin.test.ts +0 -820
  773. package/templates/docker/src/api/__tests__/auth.test.ts +0 -165
  774. package/templates/docker/src/api/__tests__/chat.test.ts +0 -376
  775. package/templates/docker/src/api/__tests__/conversations.test.ts +0 -555
  776. package/templates/docker/src/api/__tests__/cors.test.ts +0 -135
  777. package/templates/docker/src/api/__tests__/health-plugin.test.ts +0 -176
  778. package/templates/docker/src/api/__tests__/health.test.ts +0 -283
  779. package/templates/docker/src/api/__tests__/query.test.ts +0 -891
  780. package/templates/docker/src/api/__tests__/scheduled-tasks.test.ts +0 -601
  781. package/templates/docker/src/api/__tests__/slack.test.ts +0 -847
  782. package/templates/docker/src/lib/__tests__/agent-cache.test.ts +0 -439
  783. package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +0 -131
  784. package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +0 -166
  785. package/templates/docker/src/lib/__tests__/agent-integration.test.ts +0 -516
  786. package/templates/docker/src/lib/__tests__/config-actions.test.ts +0 -166
  787. package/templates/docker/src/lib/__tests__/config.test.ts +0 -1113
  788. package/templates/docker/src/lib/__tests__/conversations.test.ts +0 -589
  789. package/templates/docker/src/lib/__tests__/errors.test.ts +0 -256
  790. package/templates/docker/src/lib/__tests__/logger.test.ts +0 -200
  791. package/templates/docker/src/lib/__tests__/plugin-aware-validation.test.ts +0 -321
  792. package/templates/docker/src/lib/__tests__/providers.test.ts +0 -130
  793. package/templates/docker/src/lib/__tests__/rls.test.ts +0 -435
  794. package/templates/docker/src/lib/__tests__/scheduled-task-types.test.ts +0 -124
  795. package/templates/docker/src/lib/__tests__/scheduled-tasks.test.ts +0 -550
  796. package/templates/docker/src/lib/__tests__/semantic-index.test.ts +0 -547
  797. package/templates/docker/src/lib/__tests__/semantic-multisource.test.ts +0 -544
  798. package/templates/docker/src/lib/__tests__/semantic.test.ts +0 -363
  799. package/templates/docker/src/lib/__tests__/startup-actions.test.ts +0 -461
  800. package/templates/docker/src/lib/__tests__/startup-first-run.test.ts +0 -429
  801. package/templates/docker/src/lib/__tests__/startup.test.ts +0 -470
  802. package/templates/docker/src/lib/__tests__/tracing.test.ts +0 -28
  803. package/templates/docker/src/lib/auth/__tests__/audit.test.ts +0 -418
  804. package/templates/docker/src/lib/auth/__tests__/byot-integration.test.ts +0 -222
  805. package/templates/docker/src/lib/auth/__tests__/byot.test.ts +0 -366
  806. package/templates/docker/src/lib/auth/__tests__/detect.test.ts +0 -190
  807. package/templates/docker/src/lib/auth/__tests__/managed.test.ts +0 -173
  808. package/templates/docker/src/lib/auth/__tests__/middleware.test.ts +0 -456
  809. package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +0 -203
  810. package/templates/docker/src/lib/auth/__tests__/permissions.test.ts +0 -225
  811. package/templates/docker/src/lib/auth/__tests__/server.test.ts +0 -34
  812. package/templates/docker/src/lib/auth/__tests__/simple-key.test.ts +0 -176
  813. package/templates/docker/src/lib/auth/__tests__/types.test.ts +0 -44
  814. package/templates/docker/src/lib/db/__tests__/connection.test.ts +0 -144
  815. package/templates/docker/src/lib/db/__tests__/internal.test.ts +0 -387
  816. package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +0 -190
  817. package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -137
  818. package/templates/docker/src/lib/db/__tests__/registry.test.ts +0 -398
  819. package/templates/docker/src/lib/db/__tests__/source-rate-limit.test.ts +0 -130
  820. package/templates/docker/src/lib/errors.ts +0 -154
  821. package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +0 -204
  822. package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +0 -529
  823. package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +0 -875
  824. package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +0 -373
  825. package/templates/docker/src/lib/plugins/__tests__/tools.test.ts +0 -49
  826. package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +0 -799
  827. package/templates/docker/src/lib/scheduler/__tests__/delivery.test.ts +0 -192
  828. package/templates/docker/src/lib/scheduler/__tests__/engine.test.ts +0 -248
  829. package/templates/docker/src/lib/scheduler/__tests__/format-email.test.ts +0 -96
  830. package/templates/docker/src/lib/scheduler/__tests__/format-slack.test.ts +0 -78
  831. package/templates/docker/src/lib/scheduler/__tests__/format-webhook.test.ts +0 -78
  832. package/templates/docker/src/lib/scheduler/index.ts +0 -7
  833. package/templates/docker/src/lib/slack/__tests__/api.test.ts +0 -160
  834. package/templates/docker/src/lib/slack/__tests__/format.test.ts +0 -237
  835. package/templates/docker/src/lib/slack/__tests__/store.test.ts +0 -188
  836. package/templates/docker/src/lib/slack/__tests__/threads.test.ts +0 -112
  837. package/templates/docker/src/lib/slack/__tests__/verify.test.ts +0 -111
  838. package/templates/docker/src/lib/tools/__tests__/action-permissions.test.ts +0 -594
  839. package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +0 -240
  840. package/templates/docker/src/lib/tools/__tests__/explore-backend.test.ts +0 -267
  841. package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +0 -506
  842. package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +0 -374
  843. package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +0 -82
  844. package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +0 -210
  845. package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +0 -515
  846. package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +0 -397
  847. package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +0 -365
  848. package/templates/docker/src/lib/tools/__tests__/python.test.ts +0 -331
  849. package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +0 -132
  850. package/templates/docker/src/lib/tools/__tests__/registry.test.ts +0 -242
  851. package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +0 -227
  852. package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +0 -100
  853. package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +0 -227
  854. package/templates/docker/src/lib/tools/__tests__/sql.test.ts +0 -709
  855. package/templates/docker/src/lib/tools/actions/__tests__/audit.test.ts +0 -211
  856. package/templates/docker/src/lib/tools/actions/__tests__/email.test.ts +0 -378
  857. package/templates/docker/src/lib/tools/actions/__tests__/handler.test.ts +0 -681
  858. package/templates/docker/src/lib/tools/actions/__tests__/jira.test.ts +0 -427
  859. package/templates/docker/src/test-setup.ts +0 -38
  860. package/templates/docker/src/types/vercel-sandbox.d.ts +0 -61
  861. package/templates/docker/src/ui/components/chat/managed-auth-card.tsx +0 -116
  862. package/templates/nextjs-standalone/src/api/__tests__/actions.test.ts +0 -683
  863. package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +0 -820
  864. package/templates/nextjs-standalone/src/api/__tests__/auth.test.ts +0 -165
  865. package/templates/nextjs-standalone/src/api/__tests__/chat.test.ts +0 -376
  866. package/templates/nextjs-standalone/src/api/__tests__/conversations.test.ts +0 -555
  867. package/templates/nextjs-standalone/src/api/__tests__/cors.test.ts +0 -135
  868. package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +0 -176
  869. package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +0 -283
  870. package/templates/nextjs-standalone/src/api/__tests__/query.test.ts +0 -891
  871. package/templates/nextjs-standalone/src/api/__tests__/scheduled-tasks.test.ts +0 -601
  872. package/templates/nextjs-standalone/src/api/__tests__/slack.test.ts +0 -847
  873. package/templates/nextjs-standalone/src/app/global-error.tsx +0 -68
  874. package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +0 -439
  875. package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +0 -131
  876. package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +0 -166
  877. package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +0 -516
  878. package/templates/nextjs-standalone/src/lib/__tests__/config-actions.test.ts +0 -166
  879. package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +0 -1113
  880. package/templates/nextjs-standalone/src/lib/__tests__/conversations.test.ts +0 -589
  881. package/templates/nextjs-standalone/src/lib/__tests__/errors.test.ts +0 -256
  882. package/templates/nextjs-standalone/src/lib/__tests__/logger.test.ts +0 -200
  883. package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +0 -321
  884. package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +0 -130
  885. package/templates/nextjs-standalone/src/lib/__tests__/rls.test.ts +0 -435
  886. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-task-types.test.ts +0 -124
  887. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-tasks.test.ts +0 -550
  888. package/templates/nextjs-standalone/src/lib/__tests__/semantic-index.test.ts +0 -547
  889. package/templates/nextjs-standalone/src/lib/__tests__/semantic-multisource.test.ts +0 -544
  890. package/templates/nextjs-standalone/src/lib/__tests__/semantic.test.ts +0 -363
  891. package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +0 -461
  892. package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +0 -429
  893. package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +0 -470
  894. package/templates/nextjs-standalone/src/lib/__tests__/tracing.test.ts +0 -28
  895. package/templates/nextjs-standalone/src/lib/auth/__tests__/audit.test.ts +0 -418
  896. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot-integration.test.ts +0 -222
  897. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot.test.ts +0 -366
  898. package/templates/nextjs-standalone/src/lib/auth/__tests__/detect.test.ts +0 -190
  899. package/templates/nextjs-standalone/src/lib/auth/__tests__/managed.test.ts +0 -173
  900. package/templates/nextjs-standalone/src/lib/auth/__tests__/middleware.test.ts +0 -456
  901. package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +0 -203
  902. package/templates/nextjs-standalone/src/lib/auth/__tests__/permissions.test.ts +0 -225
  903. package/templates/nextjs-standalone/src/lib/auth/__tests__/server.test.ts +0 -34
  904. package/templates/nextjs-standalone/src/lib/auth/__tests__/simple-key.test.ts +0 -176
  905. package/templates/nextjs-standalone/src/lib/auth/__tests__/types.test.ts +0 -44
  906. package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +0 -144
  907. package/templates/nextjs-standalone/src/lib/db/__tests__/internal.test.ts +0 -387
  908. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +0 -190
  909. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -137
  910. package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +0 -398
  911. package/templates/nextjs-standalone/src/lib/db/__tests__/source-rate-limit.test.ts +0 -130
  912. package/templates/nextjs-standalone/src/lib/errors.ts +0 -154
  913. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +0 -204
  914. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +0 -529
  915. package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +0 -875
  916. package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +0 -373
  917. package/templates/nextjs-standalone/src/lib/plugins/__tests__/tools.test.ts +0 -49
  918. package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +0 -799
  919. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/delivery.test.ts +0 -192
  920. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/engine.test.ts +0 -248
  921. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-email.test.ts +0 -96
  922. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-slack.test.ts +0 -78
  923. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-webhook.test.ts +0 -78
  924. package/templates/nextjs-standalone/src/lib/scheduler/index.ts +0 -7
  925. package/templates/nextjs-standalone/src/lib/slack/__tests__/api.test.ts +0 -160
  926. package/templates/nextjs-standalone/src/lib/slack/__tests__/format.test.ts +0 -237
  927. package/templates/nextjs-standalone/src/lib/slack/__tests__/store.test.ts +0 -188
  928. package/templates/nextjs-standalone/src/lib/slack/__tests__/threads.test.ts +0 -112
  929. package/templates/nextjs-standalone/src/lib/slack/__tests__/verify.test.ts +0 -111
  930. package/templates/nextjs-standalone/src/lib/tools/__tests__/action-permissions.test.ts +0 -594
  931. package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +0 -240
  932. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-backend.test.ts +0 -267
  933. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +0 -506
  934. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +0 -374
  935. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +0 -82
  936. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +0 -210
  937. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +0 -515
  938. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +0 -397
  939. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +0 -365
  940. package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +0 -331
  941. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +0 -132
  942. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +0 -242
  943. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +0 -227
  944. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +0 -100
  945. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +0 -227
  946. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +0 -709
  947. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/audit.test.ts +0 -211
  948. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/email.test.ts +0 -378
  949. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/handler.test.ts +0 -681
  950. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/jira.test.ts +0 -427
  951. package/templates/nextjs-standalone/src/test-setup.ts +0 -38
  952. package/templates/nextjs-standalone/src/ui/components/chat/managed-auth-card.tsx +0 -116
@@ -2,13 +2,20 @@
2
2
  * Chat route — accepts a conversation and streams agent responses.
3
3
  *
4
4
  * Middleware stack:
5
- * auth → rate limit → withRequestContext → validateEnvironment → conversation persistence → runAgent → stream.
5
+ * withRequestId → auth → rate limit → withRequestContext(user) → validateEnvironment → conversation persistence → runAgent → stream.
6
6
  */
7
7
 
8
- import { Hono } from "hono";
8
+ import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
9
+ import { Effect } from "effect";
10
+ import { runEffect } from "@atlas/api/lib/effect/hono";
11
+ import { RequestContext } from "@atlas/api/lib/effect/services";
12
+ import { HTTPException } from "hono/http-exception";
13
+ import { validationHook } from "./validation-hook";
14
+ import { withRequestId, type AuthEnv } from "./middleware";
9
15
  import { z } from "zod";
10
- import { type UIMessage } from "ai";
16
+ import { type UIMessage, createUIMessageStream, createUIMessageStreamResponse } from "ai";
11
17
  import { APICallError, LoadAPIKeyError, NoSuchModelError } from "ai";
18
+ import { matchError, isRetryableError, isChatErrorCode } from "@useatlas/types";
12
19
  import { runAgent } from "@atlas/api/lib/agent";
13
20
  import { validateEnvironment } from "@atlas/api/lib/startup";
14
21
  import { GatewayModelNotFoundError } from "@ai-sdk/gateway";
@@ -20,12 +27,17 @@ import {
20
27
  getClientIP,
21
28
  } from "@atlas/api/lib/auth/middleware";
22
29
  import { hasInternalDB } from "@atlas/api/lib/db/internal";
30
+ import { checkWorkspaceStatus } from "@atlas/api/lib/workspace";
31
+ import { checkAbuseStatus } from "@atlas/api/lib/security/abuse";
32
+ import { checkPlanLimits } from "@atlas/api/lib/billing/enforcement";
23
33
  import {
24
34
  createConversation,
25
35
  addMessage,
26
36
  getConversation,
27
37
  generateTitle,
28
38
  } from "@atlas/api/lib/conversations";
39
+ import { setStreamWriter, clearStreamWriter } from "@atlas/api/lib/tools/python-stream";
40
+ import { ErrorSchema } from "./shared-schemas";
29
41
 
30
42
  const log = createLogger("chat");
31
43
 
@@ -46,405 +58,656 @@ export const ChatRequestSchema = z.object({
46
58
  conversationId: z.string().uuid().optional(),
47
59
  });
48
60
 
49
- const chat = new Hono();
50
-
51
- chat.post("/", async (c) => {
52
- const req = c.req.raw;
53
- const requestId = crypto.randomUUID();
54
-
55
- // Auth check — before context so user identity is available to all downstream logs
56
- let authResult: AuthResult;
57
- try {
58
- authResult = await authenticateRequest(req);
59
- } catch (err) {
60
- log.error(
61
- {
62
- err: err instanceof Error ? err : new Error(String(err)),
63
- requestId,
64
- },
65
- "Auth dispatch failed",
66
- );
67
- return c.json(
68
- { error: "auth_error", message: "Authentication system error" },
69
- 500,
70
- );
71
- }
72
- if (!authResult.authenticated) {
73
- log.warn({ requestId, status: authResult.status }, "Authentication failed");
74
- return c.json(
75
- { error: "auth_error", message: authResult.error },
76
- authResult.status as 401 | 403 | 500,
77
- );
78
- }
61
+ // ---------------------------------------------------------------------------
62
+ // Route definition
63
+ // ---------------------------------------------------------------------------
79
64
 
80
- // Rate limit check — after auth so we have user identity
81
- const ip = getClientIP(req);
82
- const rateLimitKey = authResult.user?.id ?? (ip ? `ip:${ip}` : "anon");
83
- const rateCheck = checkRateLimit(rateLimitKey);
84
- if (!rateCheck.allowed) {
85
- log.warn(
86
- { requestId, rateLimitKey, retryAfterMs: rateCheck.retryAfterMs },
87
- "Rate limit exceeded",
88
- );
89
- const retryAfterSeconds = Math.ceil(
90
- (rateCheck.retryAfterMs ?? 60000) / 1000,
91
- );
92
- return c.json(
93
- {
94
- error: "rate_limited",
95
- message: "Too many requests. Please wait before trying again.",
96
- retryAfterSeconds,
65
+ const chatRoute = createRoute({
66
+ method: "post",
67
+ path: "/",
68
+ tags: ["Chat"],
69
+ summary: "Chat with the agent (streaming)",
70
+ description:
71
+ "Sends a conversation to the Atlas agent and streams the response as Server-Sent Events using the Vercel AI SDK UI message stream protocol. " +
72
+ "Each SSE event is a JSON object with a 'type' field: 'text-delta' for incremental text, 'tool-call' for tool invocations, " +
73
+ "'tool-result' for tool outputs, 'step-start' for new agent steps, and 'finish' for completion. " +
74
+ "The response includes an `x-conversation-id` header when conversation persistence is enabled.",
75
+ request: {
76
+ body: {
77
+ content: { "application/json": { schema: ChatRequestSchema } },
78
+ required: true,
79
+ },
80
+ },
81
+ responses: {
82
+ 200: {
83
+ description:
84
+ "SSE stream using the Vercel AI SDK UI message stream protocol. Each event is a JSON object with a 'type' field (text-delta, tool-call, tool-result, step-start, finish).",
85
+ content: {
86
+ "text/event-stream": { schema: z.string() },
97
87
  },
98
- { status: 429, headers: { "Retry-After": String(retryAfterSeconds) } },
99
- );
100
- }
88
+ },
89
+ 400: {
90
+ description: "Bad request (malformed JSON, missing datasource, or invalid configuration)",
91
+ content: { "application/json": { schema: ErrorSchema } },
92
+ },
93
+ 401: {
94
+ description: "Authentication required",
95
+ content: { "application/json": { schema: ErrorSchema } },
96
+ },
97
+ 403: {
98
+ description: "Forbidden — insufficient permissions",
99
+ content: { "application/json": { schema: ErrorSchema } },
100
+ },
101
+ 404: {
102
+ description: "Conversation not found (invalid conversationId)",
103
+ content: { "application/json": { schema: ErrorSchema } },
104
+ },
105
+ 422: {
106
+ description: "Validation error (invalid request body)",
107
+ content: { "application/json": { schema: ErrorSchema } },
108
+ },
109
+ 429: {
110
+ description: "Rate limit exceeded",
111
+ content: { "application/json": { schema: ErrorSchema } },
112
+ },
113
+ 500: {
114
+ description: "Internal server error",
115
+ content: { "application/json": { schema: ErrorSchema } },
116
+ },
117
+ 502: {
118
+ description: "LLM provider error",
119
+ content: { "application/json": { schema: ErrorSchema } },
120
+ },
121
+ 503: {
122
+ description: "Provider unreachable, auth error, or rate limited",
123
+ content: { "application/json": { schema: ErrorSchema } },
124
+ },
125
+ 504: {
126
+ description: "Request timed out",
127
+ content: { "application/json": { schema: ErrorSchema } },
128
+ },
129
+ },
130
+ });
101
131
 
102
- // withRequestContext binds requestId + user to AsyncLocalStorage for the
103
- // entire async call chain (including logQueryAudit deep inside executeSQL).
104
- return withRequestContext(
105
- { requestId, user: authResult.user },
106
- async () => {
107
- // Startup diagnostics fast-fail with actionable errors
108
- const diagnostics = await validateEnvironment();
109
- if (diagnostics.length > 0) {
110
- return c.json(
111
- {
112
- error: "configuration_error",
113
- message: diagnostics.map((d) => d.message).join("\n\n"),
114
- diagnostics,
115
- },
116
- 400,
117
- );
132
+ const chat = new OpenAPIHono<AuthEnv>({ defaultHook: validationHook });
133
+
134
+ chat.use(withRequestId);
135
+
136
+ chat.openapi(chatRoute, async (c) => {
137
+ return runEffect(c, Effect.gen(function* () {
138
+ const req = c.req.raw;
139
+ const { requestId } = yield* RequestContext;
140
+
141
+ // Auth check — before context so user identity is available to all downstream logs
142
+ const authAttempt = yield* Effect.tryPromise({
143
+ try: () => authenticateRequest(req),
144
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
145
+ }).pipe(Effect.either);
146
+ if (authAttempt._tag === "Left") {
147
+ log.error(
148
+ {
149
+ err: authAttempt.left,
150
+ requestId,
151
+ },
152
+ "Auth dispatch failed",
153
+ );
154
+ return c.json(
155
+ { error: "auth_error", message: "Authentication system error", retryable: false, requestId },
156
+ 500,
157
+ );
158
+ }
159
+ const authResult: AuthResult = authAttempt.right;
160
+ if (!authResult.authenticated) {
161
+ log.warn({ requestId, status: authResult.status }, "Authentication failed");
162
+ const errorBody: Record<string, unknown> = { error: "auth_error", message: authResult.error, retryable: false, requestId };
163
+ if (authResult.ssoRedirectUrl) {
164
+ errorBody.ssoRedirectUrl = authResult.ssoRedirectUrl;
118
165
  }
119
-
120
- // Datasource guard — diagnostics pass (it's a warning) but chat requires a datasource
121
- const { resolveDatasourceUrl } = await import("@atlas/api/lib/db/connection");
122
- if (!resolveDatasourceUrl()) {
123
- return c.json(
124
- {
125
- error: "no_datasource",
126
- message:
127
- "No analytics datasource configured. Set ATLAS_DATASOURCE_URL to query your data.",
128
- },
129
- 400,
130
- );
166
+ return c.json(
167
+ errorBody,
168
+ authResult.status as 401 | 403 | 500,
169
+ );
170
+ }
171
+
172
+ // Rate limit check — after auth so we have user identity
173
+ const ip = getClientIP(req);
174
+ const rateLimitKey = authResult.user?.id ?? (ip ? `ip:${ip}` : "anon");
175
+ const rateCheck = checkRateLimit(rateLimitKey);
176
+ if (!rateCheck.allowed) {
177
+ log.warn(
178
+ { requestId, rateLimitKey, retryAfterMs: rateCheck.retryAfterMs },
179
+ "Rate limit exceeded",
180
+ );
181
+ const retryAfterSeconds = Math.ceil(
182
+ (rateCheck.retryAfterMs ?? 60000) / 1000,
183
+ );
184
+ return c.json(
185
+ {
186
+ error: "rate_limited",
187
+ message: "Too many requests. Please wait before trying again.",
188
+ retryAfterSeconds,
189
+ retryable: true,
190
+ requestId,
191
+ },
192
+ { status: 429, headers: { "Retry-After": String(retryAfterSeconds) } },
193
+ );
194
+ }
195
+
196
+ // IP allowlist check — enterprise feature, after auth so we have org context
197
+ let checkIPAllowlist: ((orgId: string, clientIP: string | null) => Promise<{ allowed: boolean }>) | undefined;
198
+ const eeModule = yield* Effect.tryPromise({
199
+ try: () => import("@atlas/ee/auth/ip-allowlist"),
200
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
201
+ }).pipe(Effect.option);
202
+ if (eeModule._tag === "Some") {
203
+ checkIPAllowlist = eeModule.value.checkIPAllowlist;
204
+ }
205
+ // ee module not installed — IP allowlist feature unavailable, skip
206
+ if (checkIPAllowlist) {
207
+ const orgId = authResult.user?.activeOrganizationId;
208
+ if (orgId) {
209
+ const ipCheck = yield* Effect.promise(() => checkIPAllowlist!(orgId, ip));
210
+ if (!ipCheck.allowed) {
211
+ log.warn({ requestId, orgId, ip }, "IP not in workspace allowlist");
212
+ return c.json(
213
+ { error: "ip_not_allowed", message: "Your IP address is not in the workspace's allowlist.", retryable: false, requestId },
214
+ 403,
215
+ );
216
+ }
131
217
  }
132
-
133
- // Parse request body separately so malformed JSON gets a 400, not 500
134
- let body: unknown;
135
- try {
136
- body = await c.req.json();
137
- } catch (err) {
138
- log.warn(
139
- { err: err instanceof Error ? err : new Error(String(err)) },
140
- "Failed to parse request body",
141
- );
218
+ }
219
+
220
+ // Workspace status check — block suspended/deleted workspaces
221
+ const wsCheck = yield* Effect.promise(() => checkWorkspaceStatus(authResult.user?.activeOrganizationId));
222
+ if (!wsCheck.allowed) {
223
+ return c.json(
224
+ { error: wsCheck.errorCode, message: wsCheck.errorMessage, retryable: wsCheck.errorCode && isChatErrorCode(wsCheck.errorCode) ? isRetryableError(wsCheck.errorCode) : false, requestId },
225
+ wsCheck.httpStatus ?? 403,
226
+ );
227
+ }
228
+
229
+ // Abuse check — block suspended workspaces, reject throttled ones with 429
230
+ const abuseOrgId = authResult.user?.activeOrganizationId;
231
+ if (abuseOrgId) {
232
+ const abuse = checkAbuseStatus(abuseOrgId);
233
+ if (abuse.level === "suspended") {
234
+ log.warn({ requestId, orgId: abuseOrgId }, "Workspace suspended due to abuse");
142
235
  return c.json(
143
- {
144
- error: "invalid_request",
145
- message: "Invalid JSON body.",
146
- },
147
- 400,
236
+ { error: "workspace_suspended", message: "Workspace suspended due to unusual activity. Contact your administrator.", retryable: false, requestId },
237
+ 403,
148
238
  );
149
239
  }
150
-
151
- const parsed = ChatRequestSchema.safeParse(body);
152
- if (!parsed.success) {
240
+ if (abuse.level === "throttled" && abuse.throttleDelayMs) {
241
+ const retryAfterSeconds = Math.ceil(abuse.throttleDelayMs / 1000);
242
+ log.warn({ requestId, orgId: abuseOrgId, delayMs: abuse.throttleDelayMs }, "Workspace throttled due to abuse");
153
243
  return c.json(
154
244
  {
155
- error: "validation_error",
156
- message: "Invalid request body.",
157
- details: parsed.error.issues,
245
+ error: "workspace_throttled",
246
+ message: "Workspace is temporarily throttled due to high usage. Please retry shortly.",
247
+ retryable: true,
248
+ retryAfterSeconds,
249
+ requestId,
158
250
  },
159
- 422,
251
+ { status: 429, headers: { "Retry-After": String(retryAfterSeconds) } },
160
252
  );
161
253
  }
162
-
163
- const messages = parsed.data.messages as UIMessage[];
164
- let conversationId = parsed.data.conversationId;
165
-
166
- // Conversation persistence — Ownership verification blocks here (can 404); message writes are fire-and-forget via internalExecute.
167
- if (hasInternalDB()) {
168
- if (conversationId) {
169
- // Ownership verification — NOT best-effort, this is a security check
170
- const existing = await getConversation(conversationId, authResult.user?.id);
171
- if (!existing.ok) {
172
- return c.json({ error: "not_found", message: "Conversation not found." }, 404);
173
- }
174
- // Persist the latest user message
175
- try {
176
- const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
177
- if (lastUserMsg) {
178
- addMessage({ conversationId, role: "user", content: lastUserMsg.parts });
179
- }
180
- } catch (err) {
181
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "Failed to persist user message");
182
- }
183
- } else {
184
- try {
185
- // Create new conversation — best-effort
186
- const firstUserMsg = messages.find((m) => m.role === "user");
187
- const title = firstUserMsg
188
- ? generateTitle(
189
- firstUserMsg.parts
190
- ?.filter((p): p is { type: "text"; text: string } => p.type === "text")
191
- .map((p) => p.text)
192
- .join(" ") ?? "",
193
- )
194
- : "New conversation";
195
- const created = await createConversation({
196
- userId: authResult.user?.id,
197
- title,
198
- surface: "web",
199
- });
200
- if (created) conversationId = created.id;
201
- } catch (err) {
202
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "Failed to create conversation");
203
- }
204
- }
205
- }
206
-
207
- try {
208
- // Build a dynamic registry when actions are enabled
209
- let toolRegistry;
210
- const includeActions = process.env.ATLAS_ACTIONS_ENABLED === "true";
211
- if (includeActions) {
212
- try {
213
- const { buildRegistry } = await import("@atlas/api/lib/tools/registry");
214
- toolRegistry = await buildRegistry({ includeActions });
215
- } catch (err) {
216
- log.error(
217
- { err: err instanceof Error ? err : new Error(String(err)) },
218
- "Failed to build tool registry — falling back to default tools",
219
- );
220
- }
221
- }
222
-
223
- // Merge plugin tools (if any) on top of the current registry
224
- const { getPluginTools } = await import("@atlas/api/lib/plugins/tools");
225
- const pluginTools = getPluginTools();
226
- if (pluginTools) {
227
- const { ToolRegistry, defaultRegistry } = await import("@atlas/api/lib/tools/registry");
228
- const base = toolRegistry ?? defaultRegistry;
229
- toolRegistry = ToolRegistry.merge(base, pluginTools);
230
- toolRegistry.freeze();
231
- }
232
-
233
- const result = await runAgent({ messages, ...(toolRegistry && { tools: toolRegistry }) });
234
- const streamResponse = result.toUIMessageStreamResponse();
235
-
236
- // Set conversation ID header so the client can track continuity
237
- if (conversationId) {
238
- streamResponse.headers.set("x-conversation-id", conversationId);
239
-
240
- // Fire-and-forget: persist assistant response after stream completes
241
- const cid = conversationId;
242
- void Promise.resolve(result.text)
243
- .then((text) => {
244
- addMessage({ conversationId: cid, role: "assistant", content: [{ type: "text", text }] });
245
- })
246
- .catch((err: unknown) => {
247
- log.warn({ err: err instanceof Error ? err.message : String(err) }, "Failed to persist assistant message");
248
- });
249
- }
250
-
251
- return streamResponse;
252
- } catch (err) {
253
- const message = err instanceof Error ? err.message : "";
254
-
255
- // --- Structured AI SDK error types (checked first) ---
256
-
257
- if (GatewayModelNotFoundError.isInstance(err)) {
258
- log.error(
254
+ }
255
+
256
+ // Plan limit check — block or warn when usage approaches/exceeds plan limits
257
+ const planCheck = yield* Effect.promise(() => checkPlanLimits(authResult.user?.activeOrganizationId));
258
+ if (!planCheck.allowed) {
259
+ return c.json(
260
+ {
261
+ error: planCheck.errorCode,
262
+ message: planCheck.errorMessage,
263
+ retryable: isChatErrorCode(planCheck.errorCode) ? isRetryableError(planCheck.errorCode) : false,
264
+ requestId,
265
+ ...(planCheck.errorCode === "plan_limit_exceeded" && { usage: planCheck.usage }),
266
+ },
267
+ planCheck.httpStatus,
268
+ );
269
+ }
270
+
271
+ // Capture plan warning for response headers (set after stream is created)
272
+ const planWarning = planCheck.allowed ? planCheck.warning : undefined;
273
+
274
+ // Bind user to AsyncLocalStorage so downstream code (logQueryAudit, etc.)
275
+ // has access to user identity. The middleware already set up requestId context;
276
+ // this nested call adds the user after inline auth completes.
277
+ return withRequestContext(
278
+ { requestId, user: authResult.user },
279
+ async () => {
280
+ // Startup diagnostics — fast-fail with actionable errors
281
+ const diagnostics = await validateEnvironment();
282
+ if (diagnostics.length > 0) {
283
+ return c.json(
259
284
  {
260
- err: err instanceof Error ? err : new Error(String(err)),
261
- category: "provider_model_not_found",
285
+ error: "configuration_error",
286
+ message: diagnostics.map((d) => d.message).join("\n\n"),
287
+ diagnostics,
288
+ retryable: false,
289
+ requestId,
262
290
  },
263
- "Gateway model not found",
291
+ 400,
264
292
  );
293
+ }
294
+
295
+ // Datasource guard — diagnostics pass (it's a warning) but chat requires a datasource
296
+ const { resolveDatasourceUrl } = await import("@atlas/api/lib/db/connection");
297
+ if (!resolveDatasourceUrl()) {
265
298
  return c.json(
266
299
  {
267
- error: "provider_model_not_found",
300
+ error: "no_datasource",
268
301
  message:
269
- "Model not found on the AI Gateway. Check that your ATLAS_MODEL uses the correct provider/model format (e.g., anthropic/claude-sonnet-4.6).",
302
+ "No analytics datasource configured. Set ATLAS_DATASOURCE_URL to query your data.",
303
+ retryable: false,
304
+ requestId,
270
305
  },
271
306
  400,
272
307
  );
273
308
  }
274
-
275
- if (NoSuchModelError.isInstance(err)) {
276
- log.error(
277
- {
278
- err: err instanceof Error ? err : new Error(String(err)),
279
- category: "provider_model_not_found",
280
- },
281
- "Model not found",
309
+
310
+ // Parse request body separately so malformed JSON gets a 400, not 500
311
+ let body: unknown;
312
+ try {
313
+ body = await c.req.json();
314
+ } catch (err) {
315
+ log.warn(
316
+ { err: err instanceof Error ? err : new Error(String(err)) },
317
+ "Failed to parse request body",
282
318
  );
283
319
  return c.json(
284
320
  {
285
- error: "provider_model_not_found",
286
- message:
287
- "The configured model was not found. Check ATLAS_MODEL and ATLAS_PROVIDER settings.",
321
+ error: "invalid_request",
322
+ message: "Invalid JSON body.",
323
+ retryable: false,
324
+ requestId,
288
325
  },
289
326
  400,
290
327
  );
291
328
  }
292
-
293
- if (LoadAPIKeyError.isInstance(err)) {
294
- log.error(
295
- {
296
- err: err instanceof Error ? err : new Error(String(err)),
297
- category: "provider_auth_error",
298
- },
299
- "API key not loaded",
300
- );
329
+
330
+ const parsed = ChatRequestSchema.safeParse(body);
331
+ if (!parsed.success) {
301
332
  return c.json(
302
333
  {
303
- error: "provider_auth_error",
304
- message:
305
- "LLM provider API key could not be loaded. Check that the required API key environment variable is set.",
334
+ error: "validation_error",
335
+ message: "Invalid request body.",
336
+ details: parsed.error.issues,
337
+ retryable: false,
338
+ requestId,
306
339
  },
307
- 503,
340
+ 422,
308
341
  );
309
342
  }
310
-
311
- // APICallError carries the HTTP status code from the provider response
312
- if (APICallError.isInstance(err)) {
313
- const status = err.statusCode;
314
-
315
- if (status === 401 || status === 403) {
343
+
344
+ const messages = parsed.data.messages as UIMessage[];
345
+ let conversationId = parsed.data.conversationId;
346
+
347
+ // Conversation persistence — Ownership verification blocks here (can 404); message writes are fire-and-forget via internalExecute.
348
+ if (hasInternalDB()) {
349
+ if (conversationId) {
350
+ // Ownership verification — NOT best-effort, this is a security check
351
+ const existing = await getConversation(conversationId, authResult.user?.id);
352
+ if (!existing.ok) {
353
+ return c.json({ error: "not_found", message: "Conversation not found.", retryable: false, requestId }, 404);
354
+ }
355
+ // Persist the latest user message
356
+ try {
357
+ const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
358
+ if (lastUserMsg) {
359
+ addMessage({ conversationId, role: "user", content: lastUserMsg.parts });
360
+ }
361
+ } catch (err) {
362
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "Failed to persist user message");
363
+ }
364
+ } else {
365
+ try {
366
+ // Create new conversation — best-effort
367
+ const firstUserMsg = messages.find((m) => m.role === "user");
368
+ const title = firstUserMsg
369
+ ? generateTitle(
370
+ firstUserMsg.parts
371
+ ?.filter((p): p is { type: "text"; text: string } => p.type === "text")
372
+ .map((p) => p.text)
373
+ .join(" ") ?? "",
374
+ )
375
+ : "New conversation";
376
+ const created = await createConversation({
377
+ userId: authResult.user?.id,
378
+ title,
379
+ surface: "web",
380
+ orgId: authResult.user?.activeOrganizationId,
381
+ });
382
+ if (created) {
383
+ conversationId = created.id;
384
+ // Persist the user message that triggered conversation creation
385
+ if (firstUserMsg) {
386
+ addMessage({ conversationId, role: "user", content: firstUserMsg.parts });
387
+ }
388
+ }
389
+ } catch (err) {
390
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "Failed to create conversation");
391
+ }
392
+ }
393
+ }
394
+
395
+ try {
396
+ // Build a dynamic registry when actions are enabled
397
+ let toolRegistry: import("@atlas/api/lib/tools/registry").ToolRegistry | undefined;
398
+ const warnings: string[] = [];
399
+ const includeActions = process.env.ATLAS_ACTIONS_ENABLED === "true";
400
+ if (includeActions) {
401
+ try {
402
+ const { buildRegistry } = await import("@atlas/api/lib/tools/registry");
403
+ const result = await buildRegistry({ includeActions });
404
+ toolRegistry = result.registry;
405
+ warnings.push(...result.warnings);
406
+ } catch (err) {
407
+ const errObj = err instanceof Error ? err : new Error(String(err));
408
+ log.error(
409
+ { err: errObj },
410
+ "Failed to build tool registry — falling back to default tools",
411
+ );
412
+ warnings.push(
413
+ "Actions were requested but the tool registry failed to build. Action tools are unavailable for this session. Inform the user that actions are currently unavailable and suggest they check server logs or retry later.",
414
+ );
415
+ }
416
+ }
417
+
418
+ // Merge plugin tools (if any) on top of the current registry
419
+ const prePluginRegistry = toolRegistry;
420
+ try {
421
+ const { getPluginTools } = await import("@atlas/api/lib/plugins/tools");
422
+ const pluginTools = getPluginTools();
423
+ if (pluginTools) {
424
+ const { ToolRegistry, defaultRegistry } = await import("@atlas/api/lib/tools/registry");
425
+ const base = toolRegistry ?? defaultRegistry;
426
+ toolRegistry = ToolRegistry.merge(base, pluginTools);
427
+ toolRegistry.freeze();
428
+ }
429
+ } catch (err) {
430
+ toolRegistry = prePluginRegistry;
431
+ const errObj = err instanceof Error ? err : new Error(String(err));
316
432
  log.error(
317
- {
318
- err: err instanceof Error ? err : new Error(String(err)),
319
- category: "provider_auth_error",
320
- statusCode: status,
321
- },
322
- "Provider auth error",
433
+ { err: errObj },
434
+ "Failed to merge plugin tools continuing without plugin tools",
435
+ );
436
+ warnings.push(
437
+ `Plugin tools failed to load: ${errObj.message}. Chat will continue without plugin tools. Inform the user that plugin-provided tools are unavailable for this session.`,
438
+ );
439
+ }
440
+
441
+ // Call runAgent first so errors (provider auth, config, etc.) are
442
+ // caught by the outer try-catch and returned as proper JSON errors.
443
+ // The agent stream is then merged into a UIMessageStream that supports
444
+ // writing custom data parts (Python progress events).
445
+ const agentResult = await runAgent({
446
+ messages,
447
+ ...(toolRegistry && { tools: toolRegistry }),
448
+ conversationId,
449
+ ...(warnings.length > 0 && { warnings }),
450
+ });
451
+
452
+ // Register stream writer so Python tool can send progress events.
453
+ // The writer is set before merge() triggers tool execution reads.
454
+ const stream = createUIMessageStream({
455
+ execute: ({ writer }) => {
456
+ // Surface plan warning as a data annotation so clients can display it
457
+ if (planWarning) {
458
+ writer.write({ type: "data-plan-warning", data: planWarning });
459
+ }
460
+ setStreamWriter(requestId, writer);
461
+ writer.merge(agentResult.toUIMessageStream());
462
+ },
463
+ onFinish: () => {
464
+ clearStreamWriter(requestId);
465
+ },
466
+ onError: (error) => {
467
+ clearStreamWriter(requestId);
468
+ log.error(
469
+ { err: error instanceof Error ? error : new Error(String(error)), requestId },
470
+ "Stream error",
471
+ );
472
+ return `An error occurred while generating a response (ref: ${requestId.slice(0, 8)}). Try sending your message again.`;
473
+ },
474
+ });
475
+
476
+ const streamResponse = createUIMessageStreamResponse({
477
+ stream,
478
+ headers: {
479
+ "X-Accel-Buffering": "no",
480
+ "Cache-Control": "no-cache, no-transform",
481
+ ...(conversationId ? { "x-conversation-id": conversationId } : {}),
482
+ ...(planWarning ? { "x-plan-limit-warning": JSON.stringify(planWarning) } : {}),
483
+ },
484
+ });
485
+
486
+ // Fire-and-forget: trigger onboarding "first query" milestone.
487
+ // AtlasUser.label is the user's email in managed auth mode.
488
+ if (authResult.user?.id && authResult.user.label?.includes("@")) {
489
+ const uid = authResult.user.id;
490
+ const uemail = authResult.user.label;
491
+ const uorg = authResult.user.activeOrganizationId ?? "default";
492
+ void import("@atlas/api/lib/email/hooks")
493
+ .then(({ onFirstQueryExecuted }) => {
494
+ onFirstQueryExecuted({ userId: uid, email: uemail, orgId: uorg });
495
+ })
496
+ .catch((err: unknown) => {
497
+ log.debug({ err: err instanceof Error ? err.message : String(err) }, "Onboarding email hook not available — non-blocking");
498
+ });
499
+ }
500
+
501
+ // Fire-and-forget: persist assistant response after stream completes.
502
+ if (conversationId) {
503
+ const cid = conversationId;
504
+ void Promise.resolve(agentResult.text)
505
+ .then((text) => {
506
+ try {
507
+ addMessage({ conversationId: cid, role: "assistant", content: [{ type: "text", text }] });
508
+ } catch (persistErr) {
509
+ log.warn({ err: persistErr instanceof Error ? persistErr.message : String(persistErr), conversationId: cid }, "Failed to persist assistant message");
510
+ }
511
+ })
512
+ .catch((err: unknown) => {
513
+ log.error({ err: err instanceof Error ? err.message : String(err), conversationId: cid }, "Agent stream failed — assistant response not available");
514
+ });
515
+ }
516
+
517
+ // The streaming response is a raw Response from createUIMessageStreamResponse.
518
+ // OpenAPIHono expects typed c.json() returns, but SSE streams bypass that.
519
+ // Throw as HTTPException so the global onError handler returns the raw response
520
+ // via getResponse(), bypassing the OpenAPI typed return requirement.
521
+ throw new HTTPException(200, { res: streamResponse });
522
+ } catch (err) {
523
+ // Re-throw HTTPException (stream response) — handled by global onError
524
+ if (err instanceof HTTPException) throw err;
525
+
526
+ const errObj = err instanceof Error ? err : new Error(String(err));
527
+ const message = errObj.message;
528
+
529
+ // --- Structured AI SDK error types (checked first) ---
530
+
531
+ if (GatewayModelNotFoundError.isInstance(err)) {
532
+ log.error(
533
+ { err: errObj, category: "provider_model_not_found" },
534
+ "Gateway model not found",
323
535
  );
324
536
  return c.json(
325
537
  {
326
- error: "provider_auth_error",
538
+ error: "provider_model_not_found",
327
539
  message:
328
- "LLM provider authentication failed. Check that your API key is valid and has not expired.",
540
+ "Model not found on the AI Gateway. Check that your ATLAS_MODEL uses the correct provider/model format (e.g., anthropic/claude-sonnet-4.6).",
541
+ retryable: isRetryableError("provider_model_not_found"),
542
+ requestId,
329
543
  },
330
- 503,
544
+ 400,
331
545
  );
332
546
  }
333
-
334
- if (status === 429) {
547
+
548
+ if (NoSuchModelError.isInstance(err)) {
335
549
  log.error(
550
+ { err: errObj, category: "provider_model_not_found" },
551
+ "Model not found",
552
+ );
553
+ return c.json(
336
554
  {
337
- err: err instanceof Error ? err : new Error(String(err)),
338
- category: "provider_rate_limit",
339
- statusCode: status,
555
+ error: "provider_model_not_found",
556
+ message:
557
+ "The configured model was not found. Check ATLAS_MODEL and ATLAS_PROVIDER settings.",
558
+ retryable: isRetryableError("provider_model_not_found"),
559
+ requestId,
340
560
  },
341
- "Provider rate limit",
561
+ 400,
562
+ );
563
+ }
564
+
565
+ if (LoadAPIKeyError.isInstance(err)) {
566
+ log.error(
567
+ { err: errObj, category: "provider_auth_error" },
568
+ "API key not loaded",
342
569
  );
343
570
  return c.json(
344
571
  {
345
- error: "provider_rate_limit",
572
+ error: "provider_auth_error",
346
573
  message:
347
- "LLM provider rate limit reached. Wait a moment and try again.",
574
+ "LLM provider API key could not be loaded. Check that the required API key environment variable is set.",
575
+ retryable: isRetryableError("provider_auth_error"),
576
+ requestId,
348
577
  },
349
578
  503,
350
579
  );
351
580
  }
352
-
353
- if (status === 408 || /timeout/i.test(message)) {
581
+
582
+ // APICallError carries the HTTP status code from the provider response
583
+ if (APICallError.isInstance(err)) {
584
+ const status = err.statusCode;
585
+
586
+ if (status === 401 || status === 403) {
587
+ log.error(
588
+ { err: errObj, category: "provider_auth_error", statusCode: status },
589
+ "Provider auth error",
590
+ );
591
+ return c.json(
592
+ {
593
+ error: "provider_auth_error",
594
+ message:
595
+ "LLM provider authentication failed. Check that your API key is valid and has not expired.",
596
+ retryable: isRetryableError("provider_auth_error"),
597
+ requestId,
598
+ },
599
+ 503,
600
+ );
601
+ }
602
+
603
+ if (status === 429) {
604
+ log.error(
605
+ { err: errObj, category: "provider_rate_limit", statusCode: status },
606
+ "Provider rate limit",
607
+ );
608
+ return c.json(
609
+ {
610
+ error: "provider_rate_limit",
611
+ message:
612
+ "LLM provider rate limit reached. Wait a moment and try again.",
613
+ retryable: isRetryableError("provider_rate_limit"),
614
+ requestId,
615
+ },
616
+ 503,
617
+ );
618
+ }
619
+
620
+ if (status === 408 || /timeout/i.test(message)) {
621
+ log.error(
622
+ { err: errObj, category: "provider_timeout", statusCode: status },
623
+ "Request timed out",
624
+ );
625
+ return c.json(
626
+ {
627
+ error: "provider_timeout",
628
+ message:
629
+ "The request timed out. The LLM provider took too long to respond. " +
630
+ "Try again, or if using a local model, ensure it has sufficient resources.",
631
+ retryable: isRetryableError("provider_timeout"),
632
+ requestId,
633
+ },
634
+ 504,
635
+ );
636
+ }
637
+
638
+ // Catch-all for any other APICallError status codes (5xx, etc.)
354
639
  log.error(
355
- {
356
- err: err instanceof Error ? err : new Error(String(err)),
357
- category: "provider_timeout",
358
- statusCode: status,
359
- },
360
- "Request timed out",
640
+ { err: errObj, category: "provider_error", statusCode: status },
641
+ "Provider error",
361
642
  );
362
643
  return c.json(
363
644
  {
364
- error: "provider_timeout",
365
- message:
366
- "The request timed out. The LLM provider took too long to respond. " +
367
- "Try again, or if using a local model, ensure it has sufficient resources.",
645
+ error: "provider_error",
646
+ message: `The LLM provider returned an error (HTTP ${status}). This is usually a temporary issue. Try again in a moment.`,
647
+ retryable: isRetryableError("provider_error"),
648
+ requestId,
368
649
  },
369
- 504,
650
+ 502,
370
651
  );
371
652
  }
372
-
373
- // Catch-all for any other APICallError status codes (5xx, etc.)
374
- log.error(
375
- {
376
- err: err instanceof Error ? err : new Error(String(err)),
377
- category: "provider_error",
378
- statusCode: status,
379
- },
380
- "Provider error",
381
- );
382
- return c.json(
383
- {
384
- error: "provider_error",
385
- message: `The LLM provider returned an error (HTTP ${status}). This is usually a temporary issue. Try again in a moment.`,
386
- },
387
- 502,
388
- );
389
- }
390
-
391
- // --- Regex fallbacks for non-APICallError exceptions ---
392
-
393
- if (/timeout|timed out|AbortError/i.test(message)) {
394
- log.error(
395
- {
396
- err: err instanceof Error ? err : new Error(String(err)),
397
- category: "provider_timeout",
398
- },
399
- "Request timed out",
400
- );
401
- return c.json(
402
- {
403
- error: "provider_timeout",
404
- message:
405
- "The request timed out. The LLM provider took too long to respond. " +
406
- "Try again, or if using a local model, ensure it has sufficient resources.",
407
- },
408
- 504,
409
- );
410
- }
411
-
412
- if (/fetch failed|ECONNREFUSED|ENOTFOUND/i.test(message)) {
653
+
654
+ // --- Pattern-matched errors (non-APICallError exceptions) ---
655
+ // In the chat route, errors from runAgent are typically provider-related,
656
+ // so we override matchError's generic messages with provider-appropriate ones.
657
+
658
+ const matched = matchError(err);
659
+ if (matched) {
660
+ const isConnectionError = /ECONNREFUSED|ENOTFOUND|fetch failed/i.test(message);
661
+ const code = (matched.code === "internal_error" && isConnectionError)
662
+ ? "provider_unreachable" as const
663
+ : matched.code === "provider_unreachable" ? "provider_unreachable" as const
664
+ : matched.code;
665
+ const httpStatus = code === "rate_limited" ? 429
666
+ : code === "provider_unreachable" ? 503
667
+ : code === "provider_timeout" ? 504
668
+ : 500;
669
+ // Use provider-appropriate messages instead of database-oriented matchError defaults
670
+ const userMessage = code === "provider_unreachable"
671
+ ? "Could not reach the LLM provider. Check your network connection and provider status."
672
+ : code === "provider_timeout"
673
+ ? "The request timed out. The LLM provider took too long to respond. Try again, or if using a local model, ensure it has sufficient resources."
674
+ : matched.message;
675
+ if (code === "rate_limited") {
676
+ // Pool exhaustion is transient — warn, don't error
677
+ log.warn({ err: errObj, category: code }, "Matched error: %s", code);
678
+ return c.json(
679
+ { error: code, message: userMessage, retryable: true, retryAfterSeconds: 5, requestId },
680
+ { status: 429, headers: { "Retry-After": "5" } },
681
+ );
682
+ }
683
+ log.error({ err: errObj, category: code }, "Matched error: %s", code);
684
+ return c.json(
685
+ { error: code, message: userMessage, retryable: isRetryableError(code), requestId },
686
+ httpStatus as 429 | 500 | 503 | 504,
687
+ );
688
+ }
689
+
690
+ // Fallback — safe 500 with requestId for log correlation.
691
+ // Full error details (stack trace, original message) are serialized
692
+ // server-side via pino's err serializer; only a generic message +
693
+ // request ID reach the client.
413
694
  log.error(
414
- {
415
- err: err instanceof Error ? err : new Error(String(err)),
416
- category: "provider_unreachable",
417
- },
418
- "Provider unreachable",
695
+ { err: errObj, category: "internal_error" },
696
+ "Unclassified error",
419
697
  );
420
698
  return c.json(
421
699
  {
422
- error: "provider_unreachable",
423
- message:
424
- "Could not reach the LLM provider. Check your network connection and provider status.",
700
+ error: "internal_error",
701
+ message: `An unexpected error occurred. Quote ref ${requestId.slice(0, 8)} when reporting this issue.`,
702
+ retryable: isRetryableError("internal_error"),
703
+ requestId,
425
704
  },
426
- 503,
705
+ 500,
427
706
  );
428
707
  }
429
-
430
- // Fallback — safe 500 with requestId for correlation
431
- log.error(
432
- {
433
- err: err instanceof Error ? err : new Error(String(err)),
434
- category: "internal_error",
435
- },
436
- "Unexpected error",
437
- );
438
- return c.json(
439
- {
440
- error: "internal_error",
441
- message: `An unexpected error occurred (ref: ${requestId.slice(0, 8)}). If this persists, check the server logs.`,
442
- },
443
- 500,
444
- );
445
- }
446
- },
447
- );
708
+ },
709
+ );
710
+ }), { label: "chat" });
448
711
  });
449
712
 
450
713
  export { chat };