@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,220 @@
1
+ /**
2
+ * JIRA action — create issues via JIRA REST API v3.
3
+ *
4
+ * Exports:
5
+ * - executeJiraCreate(params) — raw JIRA API call
6
+ * - createJiraTicket — AtlasAction for the agent tool registry
7
+ */
8
+
9
+ import { tool } from "ai";
10
+ import { z } from "zod";
11
+ import type { AtlasAction } from "@atlas/api/lib/action-types";
12
+ import { buildActionRequest, handleAction } from "./handler";
13
+ import { createLogger } from "@atlas/api/lib/logger";
14
+
15
+ const log = createLogger("action:jira");
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // ADF (Atlassian Document Format) helper
19
+ // ---------------------------------------------------------------------------
20
+
21
+ /** Convert plain text to a minimal ADF document (required by JIRA v3 API). */
22
+ export function textToADF(text: string) {
23
+ const paragraphs = text
24
+ .split("\n\n")
25
+ .filter((p) => p.trim().length > 0);
26
+
27
+ // Fallback for completely empty or whitespace-only text
28
+ const segments = paragraphs.length > 0 ? paragraphs : ["(no description)"];
29
+
30
+ return {
31
+ version: 1,
32
+ type: "doc",
33
+ content: segments.map((paragraph) => ({
34
+ type: "paragraph",
35
+ content: [{ type: "text", text: paragraph }],
36
+ })),
37
+ };
38
+ }
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Raw JIRA API call
42
+ // ---------------------------------------------------------------------------
43
+
44
+ export interface JiraCreateParams {
45
+ summary: string;
46
+ description: string;
47
+ project?: string;
48
+ labels?: string[];
49
+ }
50
+
51
+ export interface JiraCreateResult {
52
+ key: string;
53
+ url: string;
54
+ }
55
+
56
+ export async function executeJiraCreate(
57
+ params: JiraCreateParams,
58
+ ): Promise<JiraCreateResult> {
59
+ const baseUrl = process.env.JIRA_BASE_URL;
60
+ const email = process.env.JIRA_EMAIL;
61
+ const apiToken = process.env.JIRA_API_TOKEN;
62
+
63
+ if (!baseUrl || !email || !apiToken) {
64
+ log.error("Missing JIRA credentials");
65
+ throw new Error(
66
+ "Missing JIRA credentials. Set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_API_TOKEN.",
67
+ );
68
+ }
69
+
70
+ const project = params.project ?? process.env.JIRA_DEFAULT_PROJECT;
71
+ if (!project) {
72
+ log.error({ summary: params.summary }, "No JIRA project specified");
73
+ throw new Error(
74
+ "No JIRA project specified. Provide a project key or set JIRA_DEFAULT_PROJECT.",
75
+ );
76
+ }
77
+
78
+ const auth = Buffer.from(`${email}:${apiToken}`).toString("base64");
79
+ const url = `${baseUrl.replace(/\/$/, "")}/rest/api/3/issue`;
80
+
81
+ const body = {
82
+ fields: {
83
+ project: { key: project },
84
+ summary: params.summary,
85
+ description: textToADF(params.description),
86
+ issuetype: { name: "Task" },
87
+ ...(params.labels?.length ? { labels: params.labels } : {}),
88
+ },
89
+ };
90
+
91
+ const response = await fetch(url, {
92
+ method: "POST",
93
+ headers: {
94
+ Authorization: `Basic ${auth}`,
95
+ "Content-Type": "application/json",
96
+ Accept: "application/json",
97
+ },
98
+ body: JSON.stringify(body),
99
+ });
100
+
101
+ if (!response.ok) {
102
+ let detail: string;
103
+ try {
104
+ const errorBody = await response.json();
105
+ // JIRA returns { errorMessages, errors } — extract actionable info without exposing internals
106
+ const messages = (errorBody as { errorMessages?: string[] }).errorMessages ?? [];
107
+ const fieldErrors = Object.entries(
108
+ (errorBody as { errors?: Record<string, string> }).errors ?? {},
109
+ ).map(([field, msg]) => `${field}: ${msg}`);
110
+ detail = [...messages, ...fieldErrors].join("; ") || `HTTP ${response.status}`;
111
+ } catch {
112
+ // JSON parsing failed — try to get raw text for diagnostics
113
+ let rawText = "";
114
+ try {
115
+ rawText = await response.text();
116
+ } catch {
117
+ // ignore — body may already be consumed
118
+ }
119
+ detail = rawText
120
+ ? `HTTP ${response.status}: ${rawText.slice(0, 200)}`
121
+ : `HTTP ${response.status}`;
122
+ }
123
+ log.error({ status: response.status, url, detail, project }, "JIRA API request failed");
124
+ throw new Error(`JIRA API error: ${detail}`);
125
+ }
126
+
127
+ let data: { key: string; self: string };
128
+ try {
129
+ data = (await response.json()) as { key: string; self: string };
130
+ } catch (err) {
131
+ log.error({ err }, "Failed to parse JIRA success response");
132
+ throw new Error(
133
+ "JIRA issue may have been created but response could not be parsed",
134
+ { cause: err },
135
+ );
136
+ }
137
+
138
+ if (!data.key) {
139
+ log.error({ data }, "JIRA response missing issue key");
140
+ throw new Error(
141
+ "JIRA issue may have been created but response could not be parsed",
142
+ );
143
+ }
144
+
145
+ return {
146
+ key: data.key,
147
+ url: `${baseUrl.replace(/\/$/, "")}/browse/${data.key}`,
148
+ };
149
+ }
150
+
151
+ // ---------------------------------------------------------------------------
152
+ // Agent tool (AtlasAction)
153
+ // ---------------------------------------------------------------------------
154
+
155
+ const CREATE_JIRA_DESCRIPTION = `### Create JIRA Ticket
156
+ Use createJiraTicket to create a new JIRA issue based on the analysis findings:
157
+ - Provide a clear, concise summary (max 255 chars)
158
+ - Include relevant details in the description
159
+ - Optionally specify a project key and labels
160
+ - The ticket will require approval before creation`;
161
+
162
+ export const createJiraTicket: AtlasAction = {
163
+ name: "createJiraTicket",
164
+ description: CREATE_JIRA_DESCRIPTION,
165
+ actionType: "jira:create",
166
+ reversible: true,
167
+ defaultApproval: "manual",
168
+ requiredCredentials: ["JIRA_BASE_URL", "JIRA_EMAIL", "JIRA_API_TOKEN"],
169
+
170
+ tool: tool({
171
+ description:
172
+ "Create a JIRA issue. Requires approval before the issue is actually created.",
173
+ inputSchema: z.object({
174
+ summary: z
175
+ .string()
176
+ .max(255)
177
+ .describe("Issue summary / title (max 255 characters)"),
178
+ description: z
179
+ .string()
180
+ .describe("Detailed issue description"),
181
+ project: z
182
+ .string()
183
+ .optional()
184
+ .describe(
185
+ "JIRA project key (e.g. 'PROJ'). Falls back to JIRA_DEFAULT_PROJECT env.",
186
+ ),
187
+ labels: z
188
+ .array(z.string())
189
+ .optional()
190
+ .describe("Optional labels to apply to the issue"),
191
+ }),
192
+ execute: async ({ summary, description, project, labels }) => {
193
+ log.info({ summary, project }, "createJiraTicket invoked");
194
+
195
+ const request = buildActionRequest({
196
+ actionType: "jira:create",
197
+ target: project ?? process.env.JIRA_DEFAULT_PROJECT ?? "unknown",
198
+ summary: `Create JIRA ticket: ${summary}`,
199
+ payload: { summary, description, project, labels },
200
+ reversible: true,
201
+ });
202
+
203
+ return handleAction(request, async (payload) => {
204
+ const result = await executeJiraCreate(
205
+ payload as unknown as JiraCreateParams,
206
+ );
207
+ return {
208
+ ...result,
209
+ // Best-effort rollback metadata — transitioning to "Closed" depends on
210
+ // the JIRA workflow configuration and is NOT guaranteed to work in all
211
+ // JIRA instances or project configurations.
212
+ rollbackInfo: {
213
+ method: "transition",
214
+ params: { issueKey: result.key, targetStatus: "Closed" },
215
+ },
216
+ };
217
+ });
218
+ },
219
+ }),
220
+ };
@@ -0,0 +1,343 @@
1
+ /**
2
+ * nsjail backend for the explore tool.
3
+ *
4
+ * Uses nsjail (Linux namespaces) to run shell commands in a
5
+ * sandboxed process. Only loaded when nsjail is available on PATH,
6
+ * ATLAS_NSJAIL_PATH is set, or ATLAS_SANDBOX=nsjail is configured.
7
+ *
8
+ * Security: the jail runs with no network (default in nsjail), read-only
9
+ * bind-mount of semantic/, writable tmpfs for scratch, and no access
10
+ * to .env or any host secrets. Process runs as nobody (65534:65534).
11
+ */
12
+
13
+ import type { ExploreBackend, ExecResult } from "./explore";
14
+ import * as fs from "fs";
15
+
16
+ /** Maximum bytes to read from stdout/stderr (1 MB). */
17
+ const MAX_OUTPUT = 1024 * 1024;
18
+
19
+ /** Read up to `max` bytes from a stream, releasing the reader on completion or error. */
20
+ async function readLimited(
21
+ stream: ReadableStream,
22
+ max: number,
23
+ ): Promise<string> {
24
+ const reader = stream.getReader();
25
+ const chunks: Uint8Array[] = [];
26
+ let total = 0;
27
+ try {
28
+ while (true) {
29
+ const { done, value } = await reader.read();
30
+ if (done) break;
31
+ total += value.byteLength;
32
+ if (total > max) {
33
+ chunks.push(value.slice(0, max - (total - value.byteLength)));
34
+ break;
35
+ }
36
+ chunks.push(value);
37
+ }
38
+ } finally {
39
+ await reader.cancel().catch(() => {});
40
+ }
41
+ return new TextDecoder().decode(Buffer.concat(chunks));
42
+ }
43
+
44
+ /** Parse a positive integer from an env var, returning defaultValue on invalid input. */
45
+ function parsePositiveInt(
46
+ envVar: string,
47
+ defaultValue: number,
48
+ name: string,
49
+ ): number {
50
+ const raw = process.env[envVar];
51
+ if (raw === undefined) return defaultValue;
52
+ const parsed = parseInt(raw, 10);
53
+ if (isNaN(parsed) || parsed <= 0) {
54
+ console.warn(
55
+ `[atlas] Invalid ${envVar}="${raw}" for ${name}, using default: ${defaultValue}`,
56
+ );
57
+ return defaultValue;
58
+ }
59
+ return parsed;
60
+ }
61
+
62
+ /** Resolve the nsjail binary path, or null if unavailable. */
63
+ export function findNsjailBinary(): string | null {
64
+ // 1. Explicit path from env
65
+ const explicit = process.env.ATLAS_NSJAIL_PATH;
66
+ if (explicit) {
67
+ try {
68
+ fs.accessSync(explicit, fs.constants.X_OK);
69
+ return explicit;
70
+ } catch (err) {
71
+ const code =
72
+ err instanceof Error && "code" in err
73
+ ? (err as NodeJS.ErrnoException).code
74
+ : "unknown";
75
+ console.error(
76
+ `[atlas] ATLAS_NSJAIL_PATH="${explicit}" is not executable (${code})`,
77
+ );
78
+ return null;
79
+ }
80
+ }
81
+
82
+ // 2. Search PATH
83
+ const pathDirs = (process.env.PATH ?? "").split(":");
84
+ for (const dir of pathDirs) {
85
+ const candidate = `${dir}/nsjail`;
86
+ try {
87
+ fs.accessSync(candidate, fs.constants.X_OK);
88
+ return candidate;
89
+ } catch {
90
+ continue;
91
+ }
92
+ }
93
+
94
+ return null;
95
+ }
96
+
97
+ /** Check whether nsjail is available on this system. */
98
+ export function isNsjailAvailable(): boolean {
99
+ return findNsjailBinary() !== null;
100
+ }
101
+
102
+ /**
103
+ * Run a minimal nsjail command to verify namespace support actually works.
104
+ *
105
+ * Exercises the exact same namespace config (user, PID, mount, network)
106
+ * that real explore commands use. Returns `{ ok: true }` if nsjail can
107
+ * create namespaces on this platform, or `{ ok: false, error }` with
108
+ * a diagnostic message otherwise.
109
+ */
110
+ export async function testNsjailCapabilities(
111
+ nsjailPath: string,
112
+ semanticRoot: string,
113
+ ): Promise<{ ok: boolean; error?: string }> {
114
+ const TIMEOUT_MS = 5000;
115
+ try {
116
+ const args = buildNsjailArgs(nsjailPath, semanticRoot, "echo nsjail-ok");
117
+ const proc = Bun.spawn(args, {
118
+ env: JAIL_ENV,
119
+ stdout: "pipe",
120
+ stderr: "pipe",
121
+ });
122
+
123
+ const timer = setTimeout(() => proc.kill(), TIMEOUT_MS);
124
+ try {
125
+ const [stdout, stderr] = await Promise.all([
126
+ readLimited(proc.stdout, MAX_OUTPUT),
127
+ readLimited(proc.stderr, MAX_OUTPUT),
128
+ ]);
129
+ const exitCode = await proc.exited;
130
+ clearTimeout(timer);
131
+
132
+ if (exitCode === 0 && stdout.includes("nsjail-ok")) {
133
+ return { ok: true };
134
+ }
135
+
136
+ return {
137
+ ok: false,
138
+ error: `nsjail exited with code ${exitCode}${stderr ? `: ${stderr.trim()}` : ""}`,
139
+ };
140
+ } catch (err) {
141
+ clearTimeout(timer);
142
+ throw err;
143
+ }
144
+ } catch (err) {
145
+ return {
146
+ ok: false,
147
+ error: err instanceof Error ? err.message : String(err),
148
+ };
149
+ }
150
+ }
151
+
152
+ /** Build the nsjail CLI args for a single command execution. */
153
+ function buildNsjailArgs(
154
+ nsjailPath: string,
155
+ semanticRoot: string,
156
+ command: string,
157
+ ): string[] {
158
+ const timeLimit = parsePositiveInt(
159
+ "ATLAS_NSJAIL_TIME_LIMIT",
160
+ 10,
161
+ "time limit",
162
+ );
163
+ const memoryLimit = parsePositiveInt(
164
+ "ATLAS_NSJAIL_MEMORY_LIMIT",
165
+ 256,
166
+ "memory limit",
167
+ );
168
+
169
+ return [
170
+ nsjailPath,
171
+ "--mode",
172
+ "o",
173
+
174
+ // Read-only bind mounts
175
+ "-R",
176
+ `${semanticRoot}:/semantic`,
177
+ "-R",
178
+ "/bin",
179
+ "-R",
180
+ "/usr/bin",
181
+ "-R",
182
+ "/lib",
183
+ "-R",
184
+ "/lib64",
185
+ "-R",
186
+ "/usr/lib",
187
+
188
+ // Minimal /dev
189
+ "-R",
190
+ "/dev/null",
191
+ "-R",
192
+ "/dev/zero",
193
+ "-R",
194
+ "/dev/urandom",
195
+
196
+ // /proc for correct namespace operation
197
+ "--proc_path",
198
+ "/proc",
199
+
200
+ // Writable tmpfs for scratch
201
+ "-T",
202
+ "/tmp",
203
+
204
+ // Working directory
205
+ "--cwd",
206
+ "/semantic",
207
+
208
+ // Network namespace is enabled by default in nsjail (no network access).
209
+ // Older versions used --clone_newnet to opt in; current versions use
210
+ // --disable_clone_newnet to opt out. No flag needed.
211
+
212
+ // Time limit
213
+ "-t",
214
+ String(timeLimit),
215
+
216
+ // Resource limits
217
+ "--rlimit_as",
218
+ String(memoryLimit),
219
+ "--rlimit_fsize",
220
+ "10",
221
+ "--rlimit_nproc",
222
+ "5",
223
+ "--rlimit_nofile",
224
+ "64",
225
+
226
+ // Run as nobody
227
+ "-u",
228
+ "65534",
229
+ "-g",
230
+ "65534",
231
+
232
+ // Suppress nsjail info logs but keep error diagnostics
233
+ "--quiet",
234
+
235
+ // Command to execute
236
+ "--",
237
+ "/bin/bash",
238
+ "-c",
239
+ command,
240
+ ];
241
+ }
242
+
243
+ /** Minimal env passed into the jail — no secrets. */
244
+ const JAIL_ENV: Record<string, string> = {
245
+ PATH: "/bin:/usr/bin",
246
+ HOME: "/tmp",
247
+ LANG: "C.UTF-8",
248
+ };
249
+
250
+ /** Callbacks injected by the explore module to avoid circular dynamic imports. */
251
+ export interface NsjailCallbacks {
252
+ onInfrastructureError: () => void;
253
+ onNsjailFailed: () => void;
254
+ }
255
+
256
+ export async function createNsjailBackend(
257
+ semanticRoot: string,
258
+ callbacks: NsjailCallbacks,
259
+ ): Promise<ExploreBackend> {
260
+ // Validate nsjail binary
261
+ const nsjailPath = findNsjailBinary();
262
+ if (!nsjailPath) {
263
+ throw new Error(
264
+ "nsjail binary not found. Install nsjail or set ATLAS_NSJAIL_PATH. " +
265
+ "In non-production environments, the system will fall back to just-bash.",
266
+ );
267
+ }
268
+
269
+ // Validate semantic root exists
270
+ try {
271
+ fs.accessSync(semanticRoot, fs.constants.R_OK);
272
+ } catch (err) {
273
+ const code =
274
+ err instanceof Error && "code" in err
275
+ ? (err as NodeJS.ErrnoException).code
276
+ : "unknown";
277
+ throw new Error(
278
+ `Semantic layer directory not readable: ${semanticRoot} (${code}). ` +
279
+ "Run 'bun run atlas -- init' to generate a semantic layer.",
280
+ { cause: err },
281
+ );
282
+ }
283
+
284
+ return {
285
+ exec: async (command: string): Promise<ExecResult> => {
286
+ let proc;
287
+ try {
288
+ const args = buildNsjailArgs(nsjailPath, semanticRoot, command);
289
+ proc = Bun.spawn(args, {
290
+ env: JAIL_ENV,
291
+ stdout: "pipe",
292
+ stderr: "pipe",
293
+ });
294
+ } catch (err) {
295
+ // Spawn itself failed — infrastructure error
296
+ const detail = err instanceof Error ? err.message : String(err);
297
+ console.error("[atlas] nsjail spawn failed:", detail);
298
+ callbacks.onInfrastructureError();
299
+ throw new Error(
300
+ `nsjail infrastructure error: ${detail}. Backend cache cleared; nsjail will be re-initialized on next explore call.`,
301
+ { cause: err },
302
+ );
303
+ }
304
+
305
+ let stdout: string, stderr: string, exitCode: number;
306
+ try {
307
+ [stdout, stderr] = await Promise.all([
308
+ readLimited(proc.stdout, MAX_OUTPUT),
309
+ readLimited(proc.stderr, MAX_OUTPUT),
310
+ ]);
311
+ exitCode = await proc.exited;
312
+ } catch (err) {
313
+ const detail = err instanceof Error ? err.message : String(err);
314
+ console.error(
315
+ `[atlas] nsjail process I/O error: ${detail} | command: ${command}`,
316
+ );
317
+ throw new Error(
318
+ `nsjail process I/O error: ${detail}`,
319
+ { cause: err },
320
+ );
321
+ }
322
+
323
+ // Interpret nsjail-specific exit codes
324
+ if (exitCode === 109) {
325
+ console.error(
326
+ "[atlas] nsjail setup failure (exit 109) — sandbox may not have been applied. stderr:",
327
+ stderr,
328
+ );
329
+ // Mark nsjail as permanently failed so the system falls back to just-bash
330
+ // (when ATLAS_SANDBOX=nsjail, getExploreBackend will still throw hard)
331
+ callbacks.onNsjailFailed();
332
+ }
333
+ if (exitCode > 128) {
334
+ const signal = exitCode - 128;
335
+ console.warn(
336
+ `[atlas] nsjail child killed by signal ${signal} | command: ${command}`,
337
+ );
338
+ }
339
+
340
+ return { stdout, stderr, exitCode };
341
+ },
342
+ };
343
+ }