@useatlas/create 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/README.md +231 -0
  2. package/index.ts +829 -0
  3. package/package.json +38 -0
  4. package/templates/docker/.env.example +67 -0
  5. package/templates/docker/Dockerfile +52 -0
  6. package/templates/docker/bin/__tests__/benchmark.test.ts +598 -0
  7. package/templates/docker/bin/__tests__/duckdb-ingest.test.ts +171 -0
  8. package/templates/docker/bin/__tests__/eval.test.ts +434 -0
  9. package/templates/docker/bin/__tests__/matview-partition.test.ts +615 -0
  10. package/templates/docker/bin/__tests__/multi-source.test.ts +113 -0
  11. package/templates/docker/bin/__tests__/plugin-cli.test.ts +322 -0
  12. package/templates/docker/bin/__tests__/profiler-heuristics.test.ts +608 -0
  13. package/templates/docker/bin/__tests__/query.test.ts +240 -0
  14. package/templates/docker/bin/__tests__/schema-drift.test.ts +542 -0
  15. package/templates/docker/bin/__tests__/view-yaml-generation.test.ts +146 -0
  16. package/templates/docker/bin/atlas.ts +5044 -0
  17. package/templates/docker/bin/benchmark.ts +695 -0
  18. package/templates/docker/bin/enrich.ts +559 -0
  19. package/templates/docker/bin/eval.ts +770 -0
  20. package/templates/docker/bin/smoke.ts +438 -0
  21. package/templates/docker/data/.gitkeep +0 -0
  22. package/templates/docker/data/cybersec.sql +1961 -0
  23. package/templates/docker/data/demo-semantic/catalog.yml +40 -0
  24. package/templates/docker/data/demo-semantic/entities/accounts.yml +170 -0
  25. package/templates/docker/data/demo-semantic/entities/companies.yml +207 -0
  26. package/templates/docker/data/demo-semantic/entities/people.yml +145 -0
  27. package/templates/docker/data/demo-semantic/glossary.yml +22 -0
  28. package/templates/docker/data/demo-semantic/metrics/accounts.yml +38 -0
  29. package/templates/docker/data/demo-semantic/metrics/companies.yml +89 -0
  30. package/templates/docker/data/demo.sql +373 -0
  31. package/templates/docker/data/ecommerce.sql +1690 -0
  32. package/templates/docker/data/init-demo-db.sql +8 -0
  33. package/templates/docker/docker-compose.yml +34 -0
  34. package/templates/docker/docs/deploy.md +390 -0
  35. package/templates/docker/eslint.config.mjs +18 -0
  36. package/templates/docker/gitignore +5 -0
  37. package/templates/docker/next.config.ts +9 -0
  38. package/templates/docker/package.json +59 -0
  39. package/templates/docker/postcss.config.mjs +8 -0
  40. package/templates/docker/public/.gitkeep +0 -0
  41. package/templates/docker/public/favicon.svg +4 -0
  42. package/templates/docker/railway.json +13 -0
  43. package/templates/docker/render.yaml +34 -0
  44. package/templates/docker/semantic/catalog.yml +5 -0
  45. package/templates/docker/semantic/entities/.gitkeep +0 -0
  46. package/templates/docker/semantic/glossary.yml +6 -0
  47. package/templates/docker/semantic/metrics/.gitkeep +0 -0
  48. package/templates/docker/sidecar/Dockerfile +28 -0
  49. package/templates/docker/sidecar/railway.json +14 -0
  50. package/templates/docker/sidecar/server.ts +188 -0
  51. package/templates/docker/src/api/__tests__/actions.test.ts +683 -0
  52. package/templates/docker/src/api/__tests__/admin.test.ts +820 -0
  53. package/templates/docker/src/api/__tests__/auth.test.ts +165 -0
  54. package/templates/docker/src/api/__tests__/chat.test.ts +376 -0
  55. package/templates/docker/src/api/__tests__/conversations.test.ts +555 -0
  56. package/templates/docker/src/api/__tests__/cors.test.ts +135 -0
  57. package/templates/docker/src/api/__tests__/health-plugin.test.ts +169 -0
  58. package/templates/docker/src/api/__tests__/health.test.ts +261 -0
  59. package/templates/docker/src/api/__tests__/query.test.ts +891 -0
  60. package/templates/docker/src/api/__tests__/scheduled-tasks.test.ts +601 -0
  61. package/templates/docker/src/api/__tests__/slack.test.ts +847 -0
  62. package/templates/docker/src/api/index.ts +117 -0
  63. package/templates/docker/src/api/routes/actions.ts +274 -0
  64. package/templates/docker/src/api/routes/admin.ts +757 -0
  65. package/templates/docker/src/api/routes/auth.ts +48 -0
  66. package/templates/docker/src/api/routes/chat.ts +465 -0
  67. package/templates/docker/src/api/routes/conversations.ts +266 -0
  68. package/templates/docker/src/api/routes/health.ts +287 -0
  69. package/templates/docker/src/api/routes/openapi.ts +390 -0
  70. package/templates/docker/src/api/routes/query.ts +318 -0
  71. package/templates/docker/src/api/routes/scheduled-tasks.ts +467 -0
  72. package/templates/docker/src/api/routes/slack.ts +611 -0
  73. package/templates/docker/src/api/server.ts +226 -0
  74. package/templates/docker/src/app/api/[...route]/route.ts +33 -0
  75. package/templates/docker/src/app/error.tsx +24 -0
  76. package/templates/docker/src/app/globals.css +126 -0
  77. package/templates/docker/src/app/layout.tsx +19 -0
  78. package/templates/docker/src/app/page.tsx +14 -0
  79. package/templates/docker/src/global.d.ts +1 -0
  80. package/templates/docker/src/lib/__tests__/agent-cache.test.ts +437 -0
  81. package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +114 -0
  82. package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
  83. package/templates/docker/src/lib/__tests__/agent-integration.test.ts +514 -0
  84. package/templates/docker/src/lib/__tests__/config-actions.test.ts +166 -0
  85. package/templates/docker/src/lib/__tests__/config.test.ts +1063 -0
  86. package/templates/docker/src/lib/__tests__/conversations.test.ts +589 -0
  87. package/templates/docker/src/lib/__tests__/errors.test.ts +256 -0
  88. package/templates/docker/src/lib/__tests__/logger.test.ts +200 -0
  89. package/templates/docker/src/lib/__tests__/providers.test.ts +99 -0
  90. package/templates/docker/src/lib/__tests__/rls.test.ts +435 -0
  91. package/templates/docker/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
  92. package/templates/docker/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
  93. package/templates/docker/src/lib/__tests__/semantic-index.test.ts +547 -0
  94. package/templates/docker/src/lib/__tests__/semantic-multisource.test.ts +544 -0
  95. package/templates/docker/src/lib/__tests__/semantic.test.ts +363 -0
  96. package/templates/docker/src/lib/__tests__/startup-actions.test.ts +452 -0
  97. package/templates/docker/src/lib/__tests__/startup.test.ts +465 -0
  98. package/templates/docker/src/lib/__tests__/tracing.test.ts +28 -0
  99. package/templates/docker/src/lib/action-types.ts +95 -0
  100. package/templates/docker/src/lib/agent-query.ts +178 -0
  101. package/templates/docker/src/lib/agent.ts +505 -0
  102. package/templates/docker/src/lib/api-url.ts +2 -0
  103. package/templates/docker/src/lib/auth/__tests__/audit.test.ts +418 -0
  104. package/templates/docker/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
  105. package/templates/docker/src/lib/auth/__tests__/byot.test.ts +366 -0
  106. package/templates/docker/src/lib/auth/__tests__/detect.test.ts +190 -0
  107. package/templates/docker/src/lib/auth/__tests__/managed.test.ts +173 -0
  108. package/templates/docker/src/lib/auth/__tests__/middleware.test.ts +456 -0
  109. package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +201 -0
  110. package/templates/docker/src/lib/auth/__tests__/permissions.test.ts +225 -0
  111. package/templates/docker/src/lib/auth/__tests__/server.test.ts +34 -0
  112. package/templates/docker/src/lib/auth/__tests__/simple-key.test.ts +176 -0
  113. package/templates/docker/src/lib/auth/__tests__/types.test.ts +44 -0
  114. package/templates/docker/src/lib/auth/audit.ts +89 -0
  115. package/templates/docker/src/lib/auth/byot.ts +158 -0
  116. package/templates/docker/src/lib/auth/client.ts +35 -0
  117. package/templates/docker/src/lib/auth/detect.ts +83 -0
  118. package/templates/docker/src/lib/auth/managed.ts +73 -0
  119. package/templates/docker/src/lib/auth/middleware.ts +208 -0
  120. package/templates/docker/src/lib/auth/migrate.ts +111 -0
  121. package/templates/docker/src/lib/auth/permissions.ts +156 -0
  122. package/templates/docker/src/lib/auth/server.ts +142 -0
  123. package/templates/docker/src/lib/auth/simple-key.ts +92 -0
  124. package/templates/docker/src/lib/auth/types.ts +49 -0
  125. package/templates/docker/src/lib/config.ts +704 -0
  126. package/templates/docker/src/lib/conversation-types.ts +29 -0
  127. package/templates/docker/src/lib/conversations.ts +270 -0
  128. package/templates/docker/src/lib/db/__tests__/connection.test.ts +69 -0
  129. package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +141 -0
  130. package/templates/docker/src/lib/db/__tests__/internal.test.ts +387 -0
  131. package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +207 -0
  132. package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
  133. package/templates/docker/src/lib/db/__tests__/registry.test.ts +595 -0
  134. package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +339 -0
  135. package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +217 -0
  136. package/templates/docker/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
  137. package/templates/docker/src/lib/db/connection.ts +753 -0
  138. package/templates/docker/src/lib/db/duckdb.ts +122 -0
  139. package/templates/docker/src/lib/db/internal.ts +273 -0
  140. package/templates/docker/src/lib/db/salesforce.ts +342 -0
  141. package/templates/docker/src/lib/db/source-rate-limit.ts +191 -0
  142. package/templates/docker/src/lib/errors.ts +154 -0
  143. package/templates/docker/src/lib/logger.ts +98 -0
  144. package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
  145. package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +529 -0
  146. package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +521 -0
  147. package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +346 -0
  148. package/templates/docker/src/lib/plugins/__tests__/tools.test.ts +49 -0
  149. package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +585 -0
  150. package/templates/docker/src/lib/plugins/hooks.ts +162 -0
  151. package/templates/docker/src/lib/plugins/index.ts +9 -0
  152. package/templates/docker/src/lib/plugins/migrate.ts +309 -0
  153. package/templates/docker/src/lib/plugins/registry.ts +231 -0
  154. package/templates/docker/src/lib/plugins/tools.ts +39 -0
  155. package/templates/docker/src/lib/plugins/wiring.ts +291 -0
  156. package/templates/docker/src/lib/providers.ts +102 -0
  157. package/templates/docker/src/lib/rls.ts +321 -0
  158. package/templates/docker/src/lib/scheduled-task-types.ts +132 -0
  159. package/templates/docker/src/lib/scheduled-tasks.ts +475 -0
  160. package/templates/docker/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
  161. package/templates/docker/src/lib/scheduler/__tests__/engine.test.ts +248 -0
  162. package/templates/docker/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
  163. package/templates/docker/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
  164. package/templates/docker/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
  165. package/templates/docker/src/lib/scheduler/delivery.ts +248 -0
  166. package/templates/docker/src/lib/scheduler/engine.ts +317 -0
  167. package/templates/docker/src/lib/scheduler/executor.ts +73 -0
  168. package/templates/docker/src/lib/scheduler/format-email.ts +109 -0
  169. package/templates/docker/src/lib/scheduler/format-slack.ts +35 -0
  170. package/templates/docker/src/lib/scheduler/format-webhook.ts +37 -0
  171. package/templates/docker/src/lib/scheduler/index.ts +7 -0
  172. package/templates/docker/src/lib/security.ts +11 -0
  173. package/templates/docker/src/lib/semantic-index.ts +503 -0
  174. package/templates/docker/src/lib/semantic.ts +387 -0
  175. package/templates/docker/src/lib/sidecar-types.ts +16 -0
  176. package/templates/docker/src/lib/slack/__tests__/api.test.ts +160 -0
  177. package/templates/docker/src/lib/slack/__tests__/format.test.ts +237 -0
  178. package/templates/docker/src/lib/slack/__tests__/store.test.ts +188 -0
  179. package/templates/docker/src/lib/slack/__tests__/threads.test.ts +112 -0
  180. package/templates/docker/src/lib/slack/__tests__/verify.test.ts +111 -0
  181. package/templates/docker/src/lib/slack/api.ts +102 -0
  182. package/templates/docker/src/lib/slack/format.ts +209 -0
  183. package/templates/docker/src/lib/slack/store.ts +107 -0
  184. package/templates/docker/src/lib/slack/threads.ts +64 -0
  185. package/templates/docker/src/lib/slack/verify.ts +71 -0
  186. package/templates/docker/src/lib/startup.ts +730 -0
  187. package/templates/docker/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
  188. package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
  189. package/templates/docker/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
  190. package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
  191. package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
  192. package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
  193. package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
  194. package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
  195. package/templates/docker/src/lib/tools/__tests__/registry.test.ts +235 -0
  196. package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
  197. package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
  198. package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
  199. package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
  200. package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
  201. package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
  202. package/templates/docker/src/lib/tools/__tests__/sql.test.ts +1012 -0
  203. package/templates/docker/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
  204. package/templates/docker/src/lib/tools/actions/__tests__/email.test.ts +378 -0
  205. package/templates/docker/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
  206. package/templates/docker/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
  207. package/templates/docker/src/lib/tools/actions/audit.ts +47 -0
  208. package/templates/docker/src/lib/tools/actions/email.ts +191 -0
  209. package/templates/docker/src/lib/tools/actions/handler.ts +591 -0
  210. package/templates/docker/src/lib/tools/actions/index.ts +23 -0
  211. package/templates/docker/src/lib/tools/actions/jira.ts +220 -0
  212. package/templates/docker/src/lib/tools/explore-nsjail.ts +343 -0
  213. package/templates/docker/src/lib/tools/explore-sandbox.ts +264 -0
  214. package/templates/docker/src/lib/tools/explore-sidecar.ts +163 -0
  215. package/templates/docker/src/lib/tools/explore.ts +379 -0
  216. package/templates/docker/src/lib/tools/registry.ts +221 -0
  217. package/templates/docker/src/lib/tools/salesforce.ts +138 -0
  218. package/templates/docker/src/lib/tools/soql-validation.ts +172 -0
  219. package/templates/docker/src/lib/tools/sql.ts +680 -0
  220. package/templates/docker/src/lib/tracing.ts +40 -0
  221. package/templates/docker/src/lib/utils.ts +6 -0
  222. package/templates/docker/src/test-setup.ts +38 -0
  223. package/templates/docker/src/types/vercel-sandbox.d.ts +54 -0
  224. package/templates/docker/src/ui/components/actions/action-approval-card.tsx +295 -0
  225. package/templates/docker/src/ui/components/actions/action-status-badge.tsx +50 -0
  226. package/templates/docker/src/ui/components/admin/admin-layout.tsx +26 -0
  227. package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +96 -0
  228. package/templates/docker/src/ui/components/admin/empty-state.tsx +24 -0
  229. package/templates/docker/src/ui/components/admin/entity-detail.tsx +233 -0
  230. package/templates/docker/src/ui/components/admin/entity-list.tsx +96 -0
  231. package/templates/docker/src/ui/components/admin/error-banner.tsx +22 -0
  232. package/templates/docker/src/ui/components/admin/feature-disabled.tsx +44 -0
  233. package/templates/docker/src/ui/components/admin/health-badge.tsx +30 -0
  234. package/templates/docker/src/ui/components/admin/loading-state.tsx +14 -0
  235. package/templates/docker/src/ui/components/admin/stat-card.tsx +32 -0
  236. package/templates/docker/src/ui/components/atlas-chat.tsx +370 -0
  237. package/templates/docker/src/ui/components/chart/chart-detection.ts +261 -0
  238. package/templates/docker/src/ui/components/chart/result-chart.tsx +375 -0
  239. package/templates/docker/src/ui/components/chat/api-key-bar.tsx +66 -0
  240. package/templates/docker/src/ui/components/chat/copy-button.tsx +25 -0
  241. package/templates/docker/src/ui/components/chat/data-table.tsx +102 -0
  242. package/templates/docker/src/ui/components/chat/error-banner.tsx +32 -0
  243. package/templates/docker/src/ui/components/chat/explore-card.tsx +41 -0
  244. package/templates/docker/src/ui/components/chat/loading-card.tsx +10 -0
  245. package/templates/docker/src/ui/components/chat/managed-auth-card.tsx +116 -0
  246. package/templates/docker/src/ui/components/chat/markdown.tsx +72 -0
  247. package/templates/docker/src/ui/components/chat/sql-block.tsx +30 -0
  248. package/templates/docker/src/ui/components/chat/sql-result-card.tsx +144 -0
  249. package/templates/docker/src/ui/components/chat/starter-prompts.ts +6 -0
  250. package/templates/docker/src/ui/components/chat/tool-part.tsx +40 -0
  251. package/templates/docker/src/ui/components/chat/typing-indicator.tsx +19 -0
  252. package/templates/docker/src/ui/components/conversations/conversation-item.tsx +120 -0
  253. package/templates/docker/src/ui/components/conversations/conversation-list.tsx +66 -0
  254. package/templates/docker/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
  255. package/templates/docker/src/ui/components/conversations/delete-confirmation.tsx +27 -0
  256. package/templates/docker/src/ui/context.tsx +78 -0
  257. package/templates/docker/src/ui/hooks/use-admin-fetch.ts +104 -0
  258. package/templates/docker/src/ui/hooks/use-conversations.ts +184 -0
  259. package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -0
  260. package/templates/docker/src/ui/lib/action-types.ts +63 -0
  261. package/templates/docker/src/ui/lib/helpers.ts +104 -0
  262. package/templates/docker/src/ui/lib/types.ts +145 -0
  263. package/templates/docker/tsconfig.json +41 -0
  264. package/templates/docker/vercel.json +3 -0
  265. package/templates/nextjs-standalone/.env.example +68 -0
  266. package/templates/nextjs-standalone/bin/__tests__/benchmark.test.ts +598 -0
  267. package/templates/nextjs-standalone/bin/__tests__/duckdb-ingest.test.ts +171 -0
  268. package/templates/nextjs-standalone/bin/__tests__/eval.test.ts +434 -0
  269. package/templates/nextjs-standalone/bin/__tests__/matview-partition.test.ts +615 -0
  270. package/templates/nextjs-standalone/bin/__tests__/multi-source.test.ts +113 -0
  271. package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +322 -0
  272. package/templates/nextjs-standalone/bin/__tests__/profiler-heuristics.test.ts +608 -0
  273. package/templates/nextjs-standalone/bin/__tests__/query.test.ts +240 -0
  274. package/templates/nextjs-standalone/bin/__tests__/schema-drift.test.ts +542 -0
  275. package/templates/nextjs-standalone/bin/__tests__/view-yaml-generation.test.ts +146 -0
  276. package/templates/nextjs-standalone/bin/atlas.ts +5044 -0
  277. package/templates/nextjs-standalone/bin/benchmark.ts +695 -0
  278. package/templates/nextjs-standalone/bin/enrich.ts +559 -0
  279. package/templates/nextjs-standalone/bin/eval.ts +770 -0
  280. package/templates/nextjs-standalone/bin/smoke.ts +438 -0
  281. package/templates/nextjs-standalone/data/.gitkeep +0 -0
  282. package/templates/nextjs-standalone/data/cybersec.sql +1961 -0
  283. package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +40 -0
  284. package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +170 -0
  285. package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +207 -0
  286. package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +145 -0
  287. package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +22 -0
  288. package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +38 -0
  289. package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +89 -0
  290. package/templates/nextjs-standalone/data/demo.sql +373 -0
  291. package/templates/nextjs-standalone/data/ecommerce.sql +1690 -0
  292. package/templates/nextjs-standalone/data/init-demo-db.sql +8 -0
  293. package/templates/nextjs-standalone/docs/deploy.md +390 -0
  294. package/templates/nextjs-standalone/eslint.config.mjs +18 -0
  295. package/templates/nextjs-standalone/gitignore +5 -0
  296. package/templates/nextjs-standalone/next.config.ts +10 -0
  297. package/templates/nextjs-standalone/package.json +63 -0
  298. package/templates/nextjs-standalone/postcss.config.mjs +8 -0
  299. package/templates/nextjs-standalone/semantic/catalog.yml +5 -0
  300. package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
  301. package/templates/nextjs-standalone/semantic/glossary.yml +6 -0
  302. package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
  303. package/templates/nextjs-standalone/src/api/__tests__/actions.test.ts +683 -0
  304. package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +820 -0
  305. package/templates/nextjs-standalone/src/api/__tests__/auth.test.ts +165 -0
  306. package/templates/nextjs-standalone/src/api/__tests__/chat.test.ts +376 -0
  307. package/templates/nextjs-standalone/src/api/__tests__/conversations.test.ts +555 -0
  308. package/templates/nextjs-standalone/src/api/__tests__/cors.test.ts +135 -0
  309. package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +169 -0
  310. package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +261 -0
  311. package/templates/nextjs-standalone/src/api/__tests__/query.test.ts +891 -0
  312. package/templates/nextjs-standalone/src/api/__tests__/scheduled-tasks.test.ts +601 -0
  313. package/templates/nextjs-standalone/src/api/__tests__/slack.test.ts +847 -0
  314. package/templates/nextjs-standalone/src/api/index.ts +117 -0
  315. package/templates/nextjs-standalone/src/api/routes/actions.ts +274 -0
  316. package/templates/nextjs-standalone/src/api/routes/admin.ts +757 -0
  317. package/templates/nextjs-standalone/src/api/routes/auth.ts +48 -0
  318. package/templates/nextjs-standalone/src/api/routes/chat.ts +465 -0
  319. package/templates/nextjs-standalone/src/api/routes/conversations.ts +266 -0
  320. package/templates/nextjs-standalone/src/api/routes/health.ts +287 -0
  321. package/templates/nextjs-standalone/src/api/routes/openapi.ts +390 -0
  322. package/templates/nextjs-standalone/src/api/routes/query.ts +318 -0
  323. package/templates/nextjs-standalone/src/api/routes/scheduled-tasks.ts +467 -0
  324. package/templates/nextjs-standalone/src/api/routes/slack.ts +611 -0
  325. package/templates/nextjs-standalone/src/api/server.ts +226 -0
  326. package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +33 -0
  327. package/templates/nextjs-standalone/src/app/error.tsx +24 -0
  328. package/templates/nextjs-standalone/src/app/global-error.tsx +68 -0
  329. package/templates/nextjs-standalone/src/app/globals.css +126 -0
  330. package/templates/nextjs-standalone/src/app/layout.tsx +19 -0
  331. package/templates/nextjs-standalone/src/app/page.tsx +14 -0
  332. package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +437 -0
  333. package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +114 -0
  334. package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
  335. package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +514 -0
  336. package/templates/nextjs-standalone/src/lib/__tests__/config-actions.test.ts +166 -0
  337. package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +1063 -0
  338. package/templates/nextjs-standalone/src/lib/__tests__/conversations.test.ts +589 -0
  339. package/templates/nextjs-standalone/src/lib/__tests__/errors.test.ts +256 -0
  340. package/templates/nextjs-standalone/src/lib/__tests__/logger.test.ts +200 -0
  341. package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +99 -0
  342. package/templates/nextjs-standalone/src/lib/__tests__/rls.test.ts +435 -0
  343. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
  344. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
  345. package/templates/nextjs-standalone/src/lib/__tests__/semantic-index.test.ts +547 -0
  346. package/templates/nextjs-standalone/src/lib/__tests__/semantic-multisource.test.ts +544 -0
  347. package/templates/nextjs-standalone/src/lib/__tests__/semantic.test.ts +363 -0
  348. package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +452 -0
  349. package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +465 -0
  350. package/templates/nextjs-standalone/src/lib/__tests__/tracing.test.ts +28 -0
  351. package/templates/nextjs-standalone/src/lib/action-types.ts +95 -0
  352. package/templates/nextjs-standalone/src/lib/agent-query.ts +178 -0
  353. package/templates/nextjs-standalone/src/lib/agent.ts +505 -0
  354. package/templates/nextjs-standalone/src/lib/api-url.ts +3 -0
  355. package/templates/nextjs-standalone/src/lib/auth/__tests__/audit.test.ts +418 -0
  356. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
  357. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot.test.ts +366 -0
  358. package/templates/nextjs-standalone/src/lib/auth/__tests__/detect.test.ts +190 -0
  359. package/templates/nextjs-standalone/src/lib/auth/__tests__/managed.test.ts +173 -0
  360. package/templates/nextjs-standalone/src/lib/auth/__tests__/middleware.test.ts +456 -0
  361. package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +201 -0
  362. package/templates/nextjs-standalone/src/lib/auth/__tests__/permissions.test.ts +225 -0
  363. package/templates/nextjs-standalone/src/lib/auth/__tests__/server.test.ts +34 -0
  364. package/templates/nextjs-standalone/src/lib/auth/__tests__/simple-key.test.ts +176 -0
  365. package/templates/nextjs-standalone/src/lib/auth/__tests__/types.test.ts +44 -0
  366. package/templates/nextjs-standalone/src/lib/auth/audit.ts +89 -0
  367. package/templates/nextjs-standalone/src/lib/auth/byot.ts +158 -0
  368. package/templates/nextjs-standalone/src/lib/auth/client.ts +23 -0
  369. package/templates/nextjs-standalone/src/lib/auth/detect.ts +83 -0
  370. package/templates/nextjs-standalone/src/lib/auth/managed.ts +73 -0
  371. package/templates/nextjs-standalone/src/lib/auth/middleware.ts +208 -0
  372. package/templates/nextjs-standalone/src/lib/auth/migrate.ts +111 -0
  373. package/templates/nextjs-standalone/src/lib/auth/permissions.ts +156 -0
  374. package/templates/nextjs-standalone/src/lib/auth/server.ts +142 -0
  375. package/templates/nextjs-standalone/src/lib/auth/simple-key.ts +92 -0
  376. package/templates/nextjs-standalone/src/lib/auth/types.ts +49 -0
  377. package/templates/nextjs-standalone/src/lib/config.ts +704 -0
  378. package/templates/nextjs-standalone/src/lib/conversation-types.ts +29 -0
  379. package/templates/nextjs-standalone/src/lib/conversations.ts +270 -0
  380. package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +69 -0
  381. package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +141 -0
  382. package/templates/nextjs-standalone/src/lib/db/__tests__/internal.test.ts +387 -0
  383. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +207 -0
  384. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
  385. package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +595 -0
  386. package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +339 -0
  387. package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +217 -0
  388. package/templates/nextjs-standalone/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
  389. package/templates/nextjs-standalone/src/lib/db/connection.ts +753 -0
  390. package/templates/nextjs-standalone/src/lib/db/duckdb.ts +122 -0
  391. package/templates/nextjs-standalone/src/lib/db/internal.ts +273 -0
  392. package/templates/nextjs-standalone/src/lib/db/salesforce.ts +342 -0
  393. package/templates/nextjs-standalone/src/lib/db/source-rate-limit.ts +191 -0
  394. package/templates/nextjs-standalone/src/lib/errors.ts +154 -0
  395. package/templates/nextjs-standalone/src/lib/logger.ts +98 -0
  396. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
  397. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +529 -0
  398. package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +521 -0
  399. package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +346 -0
  400. package/templates/nextjs-standalone/src/lib/plugins/__tests__/tools.test.ts +49 -0
  401. package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +585 -0
  402. package/templates/nextjs-standalone/src/lib/plugins/hooks.ts +162 -0
  403. package/templates/nextjs-standalone/src/lib/plugins/index.ts +9 -0
  404. package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +309 -0
  405. package/templates/nextjs-standalone/src/lib/plugins/registry.ts +231 -0
  406. package/templates/nextjs-standalone/src/lib/plugins/tools.ts +39 -0
  407. package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +291 -0
  408. package/templates/nextjs-standalone/src/lib/providers.ts +102 -0
  409. package/templates/nextjs-standalone/src/lib/rls.ts +321 -0
  410. package/templates/nextjs-standalone/src/lib/scheduled-task-types.ts +132 -0
  411. package/templates/nextjs-standalone/src/lib/scheduled-tasks.ts +475 -0
  412. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
  413. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/engine.test.ts +248 -0
  414. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
  415. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
  416. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
  417. package/templates/nextjs-standalone/src/lib/scheduler/delivery.ts +248 -0
  418. package/templates/nextjs-standalone/src/lib/scheduler/engine.ts +317 -0
  419. package/templates/nextjs-standalone/src/lib/scheduler/executor.ts +73 -0
  420. package/templates/nextjs-standalone/src/lib/scheduler/format-email.ts +109 -0
  421. package/templates/nextjs-standalone/src/lib/scheduler/format-slack.ts +35 -0
  422. package/templates/nextjs-standalone/src/lib/scheduler/format-webhook.ts +37 -0
  423. package/templates/nextjs-standalone/src/lib/scheduler/index.ts +7 -0
  424. package/templates/nextjs-standalone/src/lib/security.ts +11 -0
  425. package/templates/nextjs-standalone/src/lib/semantic-index.ts +503 -0
  426. package/templates/nextjs-standalone/src/lib/semantic.ts +387 -0
  427. package/templates/nextjs-standalone/src/lib/sidecar-types.ts +16 -0
  428. package/templates/nextjs-standalone/src/lib/slack/__tests__/api.test.ts +160 -0
  429. package/templates/nextjs-standalone/src/lib/slack/__tests__/format.test.ts +237 -0
  430. package/templates/nextjs-standalone/src/lib/slack/__tests__/store.test.ts +188 -0
  431. package/templates/nextjs-standalone/src/lib/slack/__tests__/threads.test.ts +112 -0
  432. package/templates/nextjs-standalone/src/lib/slack/__tests__/verify.test.ts +111 -0
  433. package/templates/nextjs-standalone/src/lib/slack/api.ts +102 -0
  434. package/templates/nextjs-standalone/src/lib/slack/format.ts +209 -0
  435. package/templates/nextjs-standalone/src/lib/slack/store.ts +107 -0
  436. package/templates/nextjs-standalone/src/lib/slack/threads.ts +64 -0
  437. package/templates/nextjs-standalone/src/lib/slack/verify.ts +71 -0
  438. package/templates/nextjs-standalone/src/lib/startup.ts +730 -0
  439. package/templates/nextjs-standalone/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
  440. package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
  441. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
  442. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
  443. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
  444. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
  445. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
  446. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
  447. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +235 -0
  448. package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
  449. package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
  450. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
  451. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
  452. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
  453. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
  454. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +1012 -0
  455. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
  456. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/email.test.ts +378 -0
  457. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
  458. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
  459. package/templates/nextjs-standalone/src/lib/tools/actions/audit.ts +47 -0
  460. package/templates/nextjs-standalone/src/lib/tools/actions/email.ts +191 -0
  461. package/templates/nextjs-standalone/src/lib/tools/actions/handler.ts +591 -0
  462. package/templates/nextjs-standalone/src/lib/tools/actions/index.ts +23 -0
  463. package/templates/nextjs-standalone/src/lib/tools/actions/jira.ts +220 -0
  464. package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +343 -0
  465. package/templates/nextjs-standalone/src/lib/tools/explore-sandbox.ts +264 -0
  466. package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +163 -0
  467. package/templates/nextjs-standalone/src/lib/tools/explore.ts +379 -0
  468. package/templates/nextjs-standalone/src/lib/tools/registry.ts +221 -0
  469. package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +138 -0
  470. package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +172 -0
  471. package/templates/nextjs-standalone/src/lib/tools/sql.ts +680 -0
  472. package/templates/nextjs-standalone/src/lib/tracing.ts +40 -0
  473. package/templates/nextjs-standalone/src/lib/utils.ts +6 -0
  474. package/templates/nextjs-standalone/src/test-setup.ts +38 -0
  475. package/templates/nextjs-standalone/src/ui/components/actions/action-approval-card.tsx +295 -0
  476. package/templates/nextjs-standalone/src/ui/components/actions/action-status-badge.tsx +50 -0
  477. package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +26 -0
  478. package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +96 -0
  479. package/templates/nextjs-standalone/src/ui/components/admin/empty-state.tsx +24 -0
  480. package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +233 -0
  481. package/templates/nextjs-standalone/src/ui/components/admin/entity-list.tsx +96 -0
  482. package/templates/nextjs-standalone/src/ui/components/admin/error-banner.tsx +22 -0
  483. package/templates/nextjs-standalone/src/ui/components/admin/feature-disabled.tsx +44 -0
  484. package/templates/nextjs-standalone/src/ui/components/admin/health-badge.tsx +30 -0
  485. package/templates/nextjs-standalone/src/ui/components/admin/loading-state.tsx +14 -0
  486. package/templates/nextjs-standalone/src/ui/components/admin/stat-card.tsx +32 -0
  487. package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +370 -0
  488. package/templates/nextjs-standalone/src/ui/components/chart/chart-detection.ts +261 -0
  489. package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +375 -0
  490. package/templates/nextjs-standalone/src/ui/components/chat/api-key-bar.tsx +66 -0
  491. package/templates/nextjs-standalone/src/ui/components/chat/copy-button.tsx +25 -0
  492. package/templates/nextjs-standalone/src/ui/components/chat/data-table.tsx +102 -0
  493. package/templates/nextjs-standalone/src/ui/components/chat/error-banner.tsx +32 -0
  494. package/templates/nextjs-standalone/src/ui/components/chat/explore-card.tsx +41 -0
  495. package/templates/nextjs-standalone/src/ui/components/chat/loading-card.tsx +10 -0
  496. package/templates/nextjs-standalone/src/ui/components/chat/managed-auth-card.tsx +116 -0
  497. package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +72 -0
  498. package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +30 -0
  499. package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +144 -0
  500. package/templates/nextjs-standalone/src/ui/components/chat/starter-prompts.ts +6 -0
  501. package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +40 -0
  502. package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +19 -0
  503. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +120 -0
  504. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-list.tsx +66 -0
  505. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
  506. package/templates/nextjs-standalone/src/ui/components/conversations/delete-confirmation.tsx +27 -0
  507. package/templates/nextjs-standalone/src/ui/context.tsx +78 -0
  508. package/templates/nextjs-standalone/src/ui/hooks/use-admin-fetch.ts +104 -0
  509. package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +184 -0
  510. package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -0
  511. package/templates/nextjs-standalone/src/ui/lib/action-types.ts +63 -0
  512. package/templates/nextjs-standalone/src/ui/lib/helpers.ts +104 -0
  513. package/templates/nextjs-standalone/src/ui/lib/types.ts +145 -0
  514. package/templates/nextjs-standalone/tsconfig.json +32 -0
  515. package/templates/nextjs-standalone/vercel.json +4 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Runtime plugin registry for Atlas.
3
+ *
4
+ * Manages plugin lifecycle: registration → initialization → health checks → teardown.
5
+ * Uses a structural `PluginLike` interface defined locally so `@atlas/api` does not
6
+ * depend on `@atlas/plugin-sdk`.
7
+ */
8
+
9
+ import { createLogger } from "@atlas/api/lib/logger";
10
+
11
+ const log = createLogger("plugins");
12
+
13
+ // ---------------------------------------------------------------------------
14
+ // Structural interfaces (no import from @atlas/plugin-sdk)
15
+ // ---------------------------------------------------------------------------
16
+
17
+ export interface PluginHealthResult {
18
+ healthy: boolean;
19
+ message?: string;
20
+ latencyMs?: number;
21
+ }
22
+
23
+ export type PluginType = "datasource" | "context" | "interaction" | "action" | "sandbox";
24
+ export type PluginStatus = "registered" | "initializing" | "healthy" | "unhealthy" | "teardown";
25
+
26
+ /**
27
+ * Structural plugin context (mirrors AtlasPluginContext from the SDK).
28
+ * Built at boot time from Atlas internals, passed to initialize().
29
+ */
30
+ export interface PluginContextLike {
31
+ db: { query(sql: string, params?: unknown[]): Promise<unknown>; execute(sql: string, params?: unknown[]): Promise<void> } | null;
32
+ connections: { get(id: string): unknown; list(): string[] };
33
+ tools: { register(tool: { name: string; description: string; tool: unknown }): void };
34
+ logger: Record<string, unknown>;
35
+ config: Record<string, unknown>;
36
+ }
37
+
38
+ /**
39
+ * Structural interface matching AtlasPlugin from the SDK. The registry
40
+ * accepts any object satisfying this shape — no hard dependency on the SDK.
41
+ */
42
+ export interface PluginLike {
43
+ readonly id: string;
44
+ readonly type: PluginType;
45
+ readonly version: string;
46
+ readonly name?: string;
47
+ initialize?(ctx: PluginContextLike): Promise<void>;
48
+ healthCheck?(): Promise<PluginHealthResult>;
49
+ teardown?(): Promise<void>;
50
+ // Additional properties from specific plugin types are accessed via
51
+ // type-narrowing in wiring.ts using structural checks.
52
+ readonly [key: string]: unknown;
53
+ }
54
+
55
+ interface PluginEntry {
56
+ plugin: PluginLike;
57
+ status: PluginStatus;
58
+ }
59
+
60
+ export interface PluginDescription {
61
+ id: string;
62
+ type: PluginType;
63
+ version: string;
64
+ name: string;
65
+ status: PluginStatus;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Registry
70
+ // ---------------------------------------------------------------------------
71
+
72
+ export class PluginRegistry {
73
+ private entries: PluginEntry[] = [];
74
+ private idSet = new Set<string>();
75
+ private initialized = false;
76
+
77
+ register(plugin: PluginLike): void {
78
+ if (!plugin.id || !plugin.id.trim()) {
79
+ throw new Error("Plugin id must not be empty");
80
+ }
81
+ if (this.idSet.has(plugin.id)) {
82
+ throw new Error(`Plugin "${plugin.id}" is already registered`);
83
+ }
84
+ this.idSet.add(plugin.id);
85
+ this.entries.push({ plugin, status: "registered" });
86
+ log.info({ pluginId: plugin.id, type: plugin.type }, "Plugin registered");
87
+ }
88
+
89
+ /**
90
+ * Initialize all registered plugins sequentially. Each plugin's
91
+ * `initialize(ctx)` receives the Atlas context (db, connections, tools,
92
+ * logger, config). Plugins without an `initialize` method are marked
93
+ * healthy immediately. Failures set "unhealthy" + log — they don't crash.
94
+ */
95
+ async initializeAll(ctx: PluginContextLike): Promise<{ succeeded: string[]; failed: string[] }> {
96
+ if (this.initialized) {
97
+ throw new Error("Plugins already initialized — initializeAll() cannot be called twice");
98
+ }
99
+ this.initialized = true;
100
+
101
+ const succeeded: string[] = [];
102
+ const failed: string[] = [];
103
+
104
+ for (const entry of this.entries) {
105
+ entry.status = "initializing";
106
+ if (!entry.plugin.initialize) {
107
+ entry.status = "healthy";
108
+ succeeded.push(entry.plugin.id);
109
+ continue;
110
+ }
111
+ try {
112
+ const pluginCtx = {
113
+ ...ctx,
114
+ logger: typeof (ctx.logger as Record<string, unknown>)?.child === "function"
115
+ ? (ctx.logger as { child(bindings: Record<string, unknown>): unknown }).child({ pluginId: entry.plugin.id })
116
+ : ctx.logger,
117
+ };
118
+ await entry.plugin.initialize(pluginCtx as PluginContextLike);
119
+ entry.status = "healthy";
120
+ succeeded.push(entry.plugin.id);
121
+ log.info({ pluginId: entry.plugin.id }, "Plugin initialized");
122
+ } catch (err) {
123
+ entry.status = "unhealthy";
124
+ failed.push(entry.plugin.id);
125
+ log.error(
126
+ { pluginId: entry.plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
127
+ "Plugin initialization failed",
128
+ );
129
+ }
130
+ }
131
+
132
+ return { succeeded, failed };
133
+ }
134
+
135
+ /**
136
+ * Run health checks on all registered plugins. Returns a map of plugin id
137
+ * to health result with current status. Catches exceptions from probes.
138
+ */
139
+ async healthCheckAll(): Promise<Map<string, PluginHealthResult & { status: PluginStatus }>> {
140
+ const results = new Map<string, PluginHealthResult & { status: PluginStatus }>();
141
+
142
+ for (const entry of this.entries) {
143
+ if (!entry.plugin.healthCheck) {
144
+ results.set(entry.plugin.id, { healthy: entry.status === "healthy", status: entry.status });
145
+ continue;
146
+ }
147
+ try {
148
+ const result = await entry.plugin.healthCheck();
149
+ entry.status = result.healthy ? "healthy" : "unhealthy";
150
+ results.set(entry.plugin.id, { ...result, status: entry.status });
151
+ } catch (err) {
152
+ entry.status = "unhealthy";
153
+ results.set(entry.plugin.id, {
154
+ healthy: false,
155
+ message: err instanceof Error ? err.message : String(err),
156
+ status: entry.status,
157
+ });
158
+ }
159
+ }
160
+
161
+ return results;
162
+ }
163
+
164
+ /**
165
+ * Tear down all plugins in reverse registration order (LIFO).
166
+ * Catches and logs errors — teardown continues for remaining plugins.
167
+ */
168
+ async teardownAll(): Promise<void> {
169
+ for (let i = this.entries.length - 1; i >= 0; i--) {
170
+ const entry = this.entries[i];
171
+ entry.status = "teardown";
172
+ if (!entry.plugin.teardown) continue;
173
+ try {
174
+ await entry.plugin.teardown();
175
+ log.info({ pluginId: entry.plugin.id }, "Plugin torn down");
176
+ } catch (err) {
177
+ log.error(
178
+ { pluginId: entry.plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
179
+ "Plugin teardown failed",
180
+ );
181
+ }
182
+ }
183
+ }
184
+
185
+ get(id: string): PluginLike | undefined {
186
+ return this.entries.find((e) => e.plugin.id === id)?.plugin;
187
+ }
188
+
189
+ getStatus(id: string): PluginStatus | undefined {
190
+ return this.entries.find((e) => e.plugin.id === id)?.status;
191
+ }
192
+
193
+ /** Return plugins of the given type that are currently healthy. */
194
+ getByType(type: PluginType): PluginLike[] {
195
+ return this.entries
196
+ .filter((e) => e.plugin.type === type && e.status === "healthy")
197
+ .map((e) => e.plugin);
198
+ }
199
+
200
+ /** Return all healthy plugins regardless of type (for cross-cutting hooks). */
201
+ getAllHealthy(): PluginLike[] {
202
+ return this.entries
203
+ .filter((e) => e.status === "healthy")
204
+ .map((e) => e.plugin);
205
+ }
206
+
207
+ /** Return metadata for all registered plugins. */
208
+ describe(): PluginDescription[] {
209
+ return this.entries.map((e) => ({
210
+ id: e.plugin.id,
211
+ type: e.plugin.type,
212
+ version: e.plugin.version,
213
+ name: e.plugin.name ?? e.plugin.id,
214
+ status: e.status,
215
+ }));
216
+ }
217
+
218
+ get size(): number {
219
+ return this.entries.length;
220
+ }
221
+
222
+ /** Reset registry state. For testing only. */
223
+ _reset(): void {
224
+ this.entries = [];
225
+ this.idSet.clear();
226
+ this.initialized = false;
227
+ }
228
+ }
229
+
230
+ /** Global singleton. */
231
+ export const plugins = new PluginRegistry();
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Plugin bridge — stores plugin tool registry and context fragments for
3
+ * use by the chat route and agent loop respectively.
4
+ *
5
+ * server.ts writes these at boot; chat.ts and agent.ts read them at runtime.
6
+ */
7
+
8
+ import type { ToolRegistry } from "@atlas/api/lib/tools/registry";
9
+
10
+ let pluginToolRegistry: ToolRegistry | undefined;
11
+ let contextFragments: string[] = [];
12
+
13
+ export function setPluginTools(registry: ToolRegistry): void {
14
+ pluginToolRegistry = registry;
15
+ }
16
+
17
+ export function getPluginTools(): ToolRegistry | undefined {
18
+ return pluginToolRegistry;
19
+ }
20
+
21
+ export function setContextFragments(fragments: string[]): void {
22
+ contextFragments = fragments;
23
+ }
24
+
25
+ export function getContextFragments(): string[] {
26
+ return contextFragments;
27
+ }
28
+
29
+ import type { DialectHint } from "./wiring";
30
+
31
+ let dialectHints: readonly DialectHint[] = [];
32
+
33
+ export function setDialectHints(hints: readonly DialectHint[]): void {
34
+ dialectHints = hints;
35
+ }
36
+
37
+ export function getDialectHints(): readonly DialectHint[] {
38
+ return dialectHints;
39
+ }
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Plugin wiring — bridges plugins into existing Atlas registries.
3
+ *
4
+ * Each function accepts DI params for testability. When registries are
5
+ * omitted, the global singletons are used.
6
+ */
7
+
8
+ import { createLogger } from "@atlas/api/lib/logger";
9
+ import type { PluginRegistry, PluginLike } from "./registry";
10
+ import type { ConnectionRegistry } from "@atlas/api/lib/db/connection";
11
+ import type { ToolRegistry, AtlasTool } from "@atlas/api/lib/tools/registry";
12
+
13
+ const log = createLogger("plugins:wiring");
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Structural checks for plugin subtypes (avoids SDK dependency)
17
+ // ---------------------------------------------------------------------------
18
+
19
+ interface ContextShape {
20
+ contextProvider: {
21
+ load(): Promise<string>;
22
+ refresh?(): Promise<void>;
23
+ };
24
+ }
25
+
26
+ interface DatasourceShape {
27
+ connection: {
28
+ create(): Promise<{ query(sql: string, timeoutMs?: number): Promise<unknown>; close(): Promise<void> }> | { query(sql: string, timeoutMs?: number): Promise<unknown>; close(): Promise<void> };
29
+ dbType: string;
30
+ validate?(query: string): { valid: boolean; reason?: string };
31
+ };
32
+ entities?: unknown[] | (() => Promise<unknown[]> | unknown[]);
33
+ dialect?: string;
34
+ }
35
+
36
+ interface ActionShape {
37
+ actions: ReadonlyArray<{
38
+ name: string;
39
+ description: string;
40
+ tool: unknown;
41
+ actionType: string;
42
+ reversible: boolean;
43
+ defaultApproval: string;
44
+ requiredCredentials: string[];
45
+ }>;
46
+ }
47
+
48
+ interface InteractionShape {
49
+ routes: (app: unknown) => void;
50
+ }
51
+
52
+ function hasContextProvider(p: PluginLike): p is PluginLike & ContextShape {
53
+ return (
54
+ p.type === "context" &&
55
+ typeof (p as Record<string, unknown>).contextProvider === "object" &&
56
+ (p as Record<string, unknown>).contextProvider !== null &&
57
+ typeof ((p as Record<string, unknown>).contextProvider as Record<string, unknown>)?.load === "function"
58
+ );
59
+ }
60
+
61
+ function hasDatasource(p: PluginLike): p is PluginLike & DatasourceShape {
62
+ return (
63
+ p.type === "datasource" &&
64
+ typeof (p as Record<string, unknown>).connection === "object" &&
65
+ (p as Record<string, unknown>).connection !== null
66
+ );
67
+ }
68
+
69
+ function hasActions(p: PluginLike): p is PluginLike & ActionShape {
70
+ return p.type === "action" && Array.isArray((p as Record<string, unknown>).actions);
71
+ }
72
+
73
+ function hasRoutes(p: PluginLike): p is PluginLike & InteractionShape {
74
+ return p.type === "interaction" && typeof (p as Record<string, unknown>).routes === "function";
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Wiring functions
79
+ // ---------------------------------------------------------------------------
80
+
81
+ export interface DialectHint {
82
+ readonly pluginId: string;
83
+ readonly dialect: string;
84
+ }
85
+
86
+ /**
87
+ * For each healthy datasource plugin, call `connection.create()` and register
88
+ * the resulting DBConnection in the ConnectionRegistry. Also resolves
89
+ * plugin-provided entities and collects dialect hints.
90
+ */
91
+ export async function wireDatasourcePlugins(
92
+ pluginRegistry: PluginRegistry,
93
+ connectionRegistry?: ConnectionRegistry,
94
+ ): Promise<{ wired: string[]; failed: Array<{ pluginId: string; error: string }>; dialectHints: DialectHint[]; entityFailures: Array<{ pluginId: string; error: string }> }> {
95
+ const connRegistry = connectionRegistry ?? (await import("@atlas/api/lib/db/connection")).connections;
96
+ const datasources = pluginRegistry.getByType("datasource");
97
+ const wired: string[] = [];
98
+ const failed: Array<{ pluginId: string; error: string }> = [];
99
+ const dialectHints: DialectHint[] = [];
100
+ const entityFailures: Array<{ pluginId: string; error: string }> = [];
101
+
102
+ for (const plugin of datasources) {
103
+ if (!hasDatasource(plugin)) {
104
+ log.warn({ pluginId: plugin.id }, "Datasource plugin missing connection property — skipped");
105
+ continue;
106
+ }
107
+ try {
108
+ const conn = await plugin.connection.create();
109
+ await connRegistry.registerDirect(
110
+ plugin.id,
111
+ conn as Parameters<ConnectionRegistry["registerDirect"]>[1],
112
+ plugin.connection.dbType as Parameters<ConnectionRegistry["registerDirect"]>[2],
113
+ plugin.name ?? plugin.id,
114
+ plugin.connection.validate,
115
+ );
116
+ wired.push(plugin.id);
117
+ log.info({ pluginId: plugin.id, dbType: plugin.connection.dbType }, "Datasource plugin wired");
118
+ } catch (err) {
119
+ const msg = err instanceof Error ? err.message : String(err);
120
+ failed.push({ pluginId: plugin.id, error: msg });
121
+ log.error(
122
+ { pluginId: plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
123
+ "Failed to wire datasource plugin",
124
+ );
125
+ continue;
126
+ }
127
+
128
+ // Resolve plugin-provided entities (in-memory, no disk writes)
129
+ if (plugin.entities !== undefined) {
130
+ try {
131
+ const resolved = typeof plugin.entities === "function"
132
+ ? await plugin.entities()
133
+ : plugin.entities;
134
+ if (resolved != null && !Array.isArray(resolved)) {
135
+ const msg = `entities factory returned non-array (${typeof resolved})`;
136
+ log.error({ pluginId: plugin.id, type: typeof resolved }, msg);
137
+ entityFailures.push({ pluginId: plugin.id, error: msg });
138
+ } else if (Array.isArray(resolved) && resolved.length === 0) {
139
+ log.warn({ pluginId: plugin.id }, "Plugin entities factory returned empty array");
140
+ } else if (Array.isArray(resolved) && resolved.length > 0) {
141
+ // Validate per-element shape: must have string name and yaml
142
+ const valid: Array<{ name: string; yaml: string }> = [];
143
+ for (const el of resolved) {
144
+ if (
145
+ el != null &&
146
+ typeof el === "object" &&
147
+ typeof (el as Record<string, unknown>).name === "string" &&
148
+ typeof (el as Record<string, unknown>).yaml === "string"
149
+ ) {
150
+ valid.push(el as { name: string; yaml: string });
151
+ } else {
152
+ log.error(
153
+ { pluginId: plugin.id, element: el },
154
+ "Invalid entity element — expected { name: string; yaml: string }, skipping",
155
+ );
156
+ }
157
+ }
158
+ if (valid.length > 0) {
159
+ const { registerPluginEntities } = await import("@atlas/api/lib/semantic");
160
+ registerPluginEntities(plugin.id, valid);
161
+ log.info({ pluginId: plugin.id, entityCount: valid.length }, "Plugin entities registered");
162
+ }
163
+ }
164
+ } catch (err) {
165
+ const msg = err instanceof Error ? err.message : String(err);
166
+ entityFailures.push({ pluginId: plugin.id, error: msg });
167
+ log.error(
168
+ { pluginId: plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
169
+ "Failed to resolve plugin entities — connection still wired",
170
+ );
171
+ }
172
+ }
173
+
174
+ // Collect dialect hints
175
+ if (typeof plugin.dialect === "string" && plugin.dialect.trim()) {
176
+ dialectHints.push({ pluginId: plugin.id, dialect: plugin.dialect });
177
+ }
178
+ }
179
+
180
+ return { wired, failed, dialectHints, entityFailures };
181
+ }
182
+
183
+ /**
184
+ * For each healthy action plugin, register each PluginAction as an AtlasTool
185
+ * in the ToolRegistry.
186
+ */
187
+ export async function wireActionPlugins(
188
+ pluginRegistry: PluginRegistry,
189
+ toolRegistry?: ToolRegistry,
190
+ ): Promise<{ wired: string[]; failed: Array<{ pluginId: string; error: string }> }> {
191
+ const registry = toolRegistry ?? (await import("@atlas/api/lib/tools/registry")).defaultRegistry;
192
+ const actionPlugins = pluginRegistry.getByType("action");
193
+ const wired: string[] = [];
194
+ const failed: Array<{ pluginId: string; error: string }> = [];
195
+
196
+ for (const plugin of actionPlugins) {
197
+ if (!hasActions(plugin)) {
198
+ log.warn({ pluginId: plugin.id }, "Action plugin missing actions array — skipped");
199
+ continue;
200
+ }
201
+ for (const action of plugin.actions) {
202
+ try {
203
+ registry.register(action as unknown as AtlasTool);
204
+ wired.push(action.name);
205
+ log.info({ pluginId: plugin.id, action: action.name }, "Action plugin tool wired");
206
+ } catch (err) {
207
+ const msg = err instanceof Error ? err.message : String(err);
208
+ failed.push({ pluginId: plugin.id, error: msg });
209
+ log.error(
210
+ { pluginId: plugin.id, action: action.name, err: err instanceof Error ? err : new Error(String(err)) },
211
+ "Failed to wire action plugin tool",
212
+ );
213
+ }
214
+ }
215
+ }
216
+
217
+ return { wired, failed };
218
+ }
219
+
220
+ /**
221
+ * For each healthy interaction plugin, call `routes(app)` to mount Hono routes.
222
+ */
223
+ export async function wireInteractionPlugins(
224
+ pluginRegistry: PluginRegistry,
225
+ app: unknown,
226
+ ): Promise<{ wired: string[]; failed: Array<{ pluginId: string; error: string }> }> {
227
+ const interactionPlugins = pluginRegistry.getByType("interaction");
228
+ const wired: string[] = [];
229
+ const failed: Array<{ pluginId: string; error: string }> = [];
230
+
231
+ for (const plugin of interactionPlugins) {
232
+ if (!hasRoutes(plugin)) {
233
+ log.debug({ pluginId: plugin.id }, "Interaction plugin has no routes — skipping route wiring");
234
+ continue;
235
+ }
236
+ try {
237
+ // Scope plugin routes under /api/plugins/:pluginId to prevent auth bypass
238
+ const { Hono } = await import("hono");
239
+ const subApp = new Hono();
240
+ plugin.routes(subApp);
241
+ (app as { route(path: string, app: unknown): void }).route(`/api/plugins/${plugin.id}`, subApp);
242
+ wired.push(plugin.id);
243
+ log.info({ pluginId: plugin.id, prefix: `/api/plugins/${plugin.id}` }, "Interaction plugin routes mounted");
244
+ } catch (err) {
245
+ const msg = err instanceof Error ? err.message : String(err);
246
+ failed.push({ pluginId: plugin.id, error: msg });
247
+ log.error(
248
+ { pluginId: plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
249
+ "Failed to wire interaction plugin routes",
250
+ );
251
+ }
252
+ }
253
+
254
+ return { wired, failed };
255
+ }
256
+
257
+ /**
258
+ * For each healthy context plugin, call `contextProvider.load()` and collect
259
+ * the returned text fragments. Fragments are injected into the agent system
260
+ * prompt to provide additional context from plugins.
261
+ */
262
+ export async function wireContextPlugins(
263
+ pluginRegistry: PluginRegistry,
264
+ ): Promise<{ fragments: string[]; failed: Array<{ pluginId: string; error: string }> }> {
265
+ const contextPlugins = pluginRegistry.getByType("context");
266
+ const fragments: string[] = [];
267
+ const failed: Array<{ pluginId: string; error: string }> = [];
268
+
269
+ for (const plugin of contextPlugins) {
270
+ if (!hasContextProvider(plugin)) {
271
+ log.warn({ pluginId: plugin.id }, "Context plugin missing contextProvider — skipped");
272
+ continue;
273
+ }
274
+ try {
275
+ const fragment = await plugin.contextProvider.load();
276
+ if (fragment.trim()) {
277
+ fragments.push(fragment);
278
+ }
279
+ log.info({ pluginId: plugin.id, fragmentLength: fragment.length }, "Context plugin loaded");
280
+ } catch (err) {
281
+ const msg = err instanceof Error ? err.message : String(err);
282
+ failed.push({ pluginId: plugin.id, error: msg });
283
+ log.error(
284
+ { pluginId: plugin.id, err: err instanceof Error ? err : new Error(String(err)) },
285
+ "Failed to load context plugin",
286
+ );
287
+ }
288
+ }
289
+
290
+ return { fragments, failed };
291
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Multi-provider LLM configuration.
3
+ *
4
+ * Set ATLAS_PROVIDER and the corresponding API key in your .env.
5
+ * Supports Anthropic, OpenAI, AWS Bedrock, Ollama, and Vercel AI Gateway.
6
+ */
7
+
8
+ import { anthropic } from "@ai-sdk/anthropic";
9
+ import { createOpenAI, openai } from "@ai-sdk/openai";
10
+ import { bedrock } from "@ai-sdk/amazon-bedrock";
11
+ import { bedrockAnthropic } from "@ai-sdk/amazon-bedrock/anthropic";
12
+ import { gateway } from "ai";
13
+ import type { LanguageModel } from "ai";
14
+
15
+ /** Provider strings accepted in ATLAS_PROVIDER. */
16
+ type ConfigProvider = "anthropic" | "openai" | "bedrock" | "ollama" | "gateway";
17
+
18
+ /** Resolved provider type (bedrock splits into bedrock vs bedrock-anthropic). */
19
+ export type ProviderType = ConfigProvider | "bedrock-anthropic";
20
+
21
+ const VALID_PROVIDERS: ReadonlySet<ConfigProvider> = new Set([
22
+ "anthropic",
23
+ "openai",
24
+ "bedrock",
25
+ "ollama",
26
+ "gateway",
27
+ ]);
28
+
29
+ const PROVIDER_DEFAULTS: Record<ConfigProvider, string> = {
30
+ anthropic: "claude-opus-4-6",
31
+ openai: "gpt-4o",
32
+ bedrock: "anthropic.claude-opus-4-6-v1:0",
33
+ ollama: "llama3.1",
34
+ gateway: "anthropic/claude-opus-4.6",
35
+ };
36
+
37
+ function isBedrockAnthropicModel(modelId: string): boolean {
38
+ return modelId.includes("anthropic") || modelId.includes("claude");
39
+ }
40
+
41
+ /**
42
+ * Read and validate ATLAS_PROVIDER / ATLAS_MODEL from env.
43
+ * Returns the validated config provider string and the resolved model ID.
44
+ */
45
+ function resolveProvider(): { provider: ConfigProvider; modelId: string } {
46
+ const raw = process.env.ATLAS_PROVIDER ?? "anthropic";
47
+ if (!VALID_PROVIDERS.has(raw as ConfigProvider)) {
48
+ throw new Error(
49
+ `Unknown provider "${raw}". Supported: ${[...VALID_PROVIDERS].join(", ")}`
50
+ );
51
+ }
52
+ // Safe: validated by VALID_PROVIDERS.has() above
53
+ const provider = raw as ConfigProvider;
54
+ const modelId = process.env.ATLAS_MODEL ?? PROVIDER_DEFAULTS[provider];
55
+ return { provider, modelId };
56
+ }
57
+
58
+ export function getProviderType(): ProviderType {
59
+ const { provider, modelId } = resolveProvider();
60
+ if (provider === "bedrock" && isBedrockAnthropicModel(modelId)) {
61
+ return "bedrock-anthropic";
62
+ }
63
+ return provider;
64
+ }
65
+
66
+ export function getModel(): LanguageModel {
67
+ const { provider, modelId } = resolveProvider();
68
+
69
+ switch (provider) {
70
+ case "anthropic":
71
+ return anthropic(modelId);
72
+
73
+ case "openai":
74
+ return openai(modelId);
75
+
76
+ case "bedrock":
77
+ return isBedrockAnthropicModel(modelId)
78
+ ? bedrockAnthropic(modelId)
79
+ : bedrock(modelId);
80
+
81
+ case "ollama": {
82
+ const ollama = createOpenAI({
83
+ baseURL: process.env.OLLAMA_BASE_URL ?? "http://localhost:11434/v1",
84
+ });
85
+ return ollama(modelId);
86
+ }
87
+
88
+ case "gateway":
89
+ if (!process.env.AI_GATEWAY_API_KEY) {
90
+ throw new Error(
91
+ "AI_GATEWAY_API_KEY is not set. The gateway provider requires an API key. " +
92
+ "Create one at https://vercel.com/~/ai/api-keys and set it in your .env file."
93
+ );
94
+ }
95
+ return gateway(modelId);
96
+
97
+ default: {
98
+ const _exhaustive: never = provider;
99
+ throw new Error(`Unknown provider "${_exhaustive}"`);
100
+ }
101
+ }
102
+ }