@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.
- package/README.md +231 -0
- package/index.ts +829 -0
- package/package.json +38 -0
- package/templates/docker/.env.example +67 -0
- package/templates/docker/Dockerfile +52 -0
- package/templates/docker/bin/__tests__/benchmark.test.ts +598 -0
- package/templates/docker/bin/__tests__/duckdb-ingest.test.ts +171 -0
- package/templates/docker/bin/__tests__/eval.test.ts +434 -0
- package/templates/docker/bin/__tests__/matview-partition.test.ts +615 -0
- package/templates/docker/bin/__tests__/multi-source.test.ts +113 -0
- package/templates/docker/bin/__tests__/plugin-cli.test.ts +322 -0
- package/templates/docker/bin/__tests__/profiler-heuristics.test.ts +608 -0
- package/templates/docker/bin/__tests__/query.test.ts +240 -0
- package/templates/docker/bin/__tests__/schema-drift.test.ts +542 -0
- package/templates/docker/bin/__tests__/view-yaml-generation.test.ts +146 -0
- package/templates/docker/bin/atlas.ts +5044 -0
- package/templates/docker/bin/benchmark.ts +695 -0
- package/templates/docker/bin/enrich.ts +559 -0
- package/templates/docker/bin/eval.ts +770 -0
- package/templates/docker/bin/smoke.ts +438 -0
- package/templates/docker/data/.gitkeep +0 -0
- package/templates/docker/data/cybersec.sql +1961 -0
- package/templates/docker/data/demo-semantic/catalog.yml +40 -0
- package/templates/docker/data/demo-semantic/entities/accounts.yml +170 -0
- package/templates/docker/data/demo-semantic/entities/companies.yml +207 -0
- package/templates/docker/data/demo-semantic/entities/people.yml +145 -0
- package/templates/docker/data/demo-semantic/glossary.yml +22 -0
- package/templates/docker/data/demo-semantic/metrics/accounts.yml +38 -0
- package/templates/docker/data/demo-semantic/metrics/companies.yml +89 -0
- package/templates/docker/data/demo.sql +373 -0
- package/templates/docker/data/ecommerce.sql +1690 -0
- package/templates/docker/data/init-demo-db.sql +8 -0
- package/templates/docker/docker-compose.yml +34 -0
- package/templates/docker/docs/deploy.md +390 -0
- package/templates/docker/eslint.config.mjs +18 -0
- package/templates/docker/gitignore +5 -0
- package/templates/docker/next.config.ts +9 -0
- package/templates/docker/package.json +59 -0
- package/templates/docker/postcss.config.mjs +8 -0
- package/templates/docker/public/.gitkeep +0 -0
- package/templates/docker/public/favicon.svg +4 -0
- package/templates/docker/railway.json +13 -0
- package/templates/docker/render.yaml +34 -0
- package/templates/docker/semantic/catalog.yml +5 -0
- package/templates/docker/semantic/entities/.gitkeep +0 -0
- package/templates/docker/semantic/glossary.yml +6 -0
- package/templates/docker/semantic/metrics/.gitkeep +0 -0
- package/templates/docker/sidecar/Dockerfile +28 -0
- package/templates/docker/sidecar/railway.json +14 -0
- package/templates/docker/sidecar/server.ts +188 -0
- package/templates/docker/src/api/__tests__/actions.test.ts +683 -0
- package/templates/docker/src/api/__tests__/admin.test.ts +820 -0
- package/templates/docker/src/api/__tests__/auth.test.ts +165 -0
- package/templates/docker/src/api/__tests__/chat.test.ts +376 -0
- package/templates/docker/src/api/__tests__/conversations.test.ts +555 -0
- package/templates/docker/src/api/__tests__/cors.test.ts +135 -0
- package/templates/docker/src/api/__tests__/health-plugin.test.ts +169 -0
- package/templates/docker/src/api/__tests__/health.test.ts +261 -0
- package/templates/docker/src/api/__tests__/query.test.ts +891 -0
- package/templates/docker/src/api/__tests__/scheduled-tasks.test.ts +601 -0
- package/templates/docker/src/api/__tests__/slack.test.ts +847 -0
- package/templates/docker/src/api/index.ts +117 -0
- package/templates/docker/src/api/routes/actions.ts +274 -0
- package/templates/docker/src/api/routes/admin.ts +757 -0
- package/templates/docker/src/api/routes/auth.ts +48 -0
- package/templates/docker/src/api/routes/chat.ts +465 -0
- package/templates/docker/src/api/routes/conversations.ts +266 -0
- package/templates/docker/src/api/routes/health.ts +287 -0
- package/templates/docker/src/api/routes/openapi.ts +390 -0
- package/templates/docker/src/api/routes/query.ts +318 -0
- package/templates/docker/src/api/routes/scheduled-tasks.ts +467 -0
- package/templates/docker/src/api/routes/slack.ts +611 -0
- package/templates/docker/src/api/server.ts +226 -0
- package/templates/docker/src/app/api/[...route]/route.ts +33 -0
- package/templates/docker/src/app/error.tsx +24 -0
- package/templates/docker/src/app/globals.css +126 -0
- package/templates/docker/src/app/layout.tsx +19 -0
- package/templates/docker/src/app/page.tsx +14 -0
- package/templates/docker/src/global.d.ts +1 -0
- package/templates/docker/src/lib/__tests__/agent-cache.test.ts +437 -0
- package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +114 -0
- package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
- package/templates/docker/src/lib/__tests__/agent-integration.test.ts +514 -0
- package/templates/docker/src/lib/__tests__/config-actions.test.ts +166 -0
- package/templates/docker/src/lib/__tests__/config.test.ts +1063 -0
- package/templates/docker/src/lib/__tests__/conversations.test.ts +589 -0
- package/templates/docker/src/lib/__tests__/errors.test.ts +256 -0
- package/templates/docker/src/lib/__tests__/logger.test.ts +200 -0
- package/templates/docker/src/lib/__tests__/providers.test.ts +99 -0
- package/templates/docker/src/lib/__tests__/rls.test.ts +435 -0
- package/templates/docker/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
- package/templates/docker/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
- package/templates/docker/src/lib/__tests__/semantic-index.test.ts +547 -0
- package/templates/docker/src/lib/__tests__/semantic-multisource.test.ts +544 -0
- package/templates/docker/src/lib/__tests__/semantic.test.ts +363 -0
- package/templates/docker/src/lib/__tests__/startup-actions.test.ts +452 -0
- package/templates/docker/src/lib/__tests__/startup.test.ts +465 -0
- package/templates/docker/src/lib/__tests__/tracing.test.ts +28 -0
- package/templates/docker/src/lib/action-types.ts +95 -0
- package/templates/docker/src/lib/agent-query.ts +178 -0
- package/templates/docker/src/lib/agent.ts +505 -0
- package/templates/docker/src/lib/api-url.ts +2 -0
- package/templates/docker/src/lib/auth/__tests__/audit.test.ts +418 -0
- package/templates/docker/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
- package/templates/docker/src/lib/auth/__tests__/byot.test.ts +366 -0
- package/templates/docker/src/lib/auth/__tests__/detect.test.ts +190 -0
- package/templates/docker/src/lib/auth/__tests__/managed.test.ts +173 -0
- package/templates/docker/src/lib/auth/__tests__/middleware.test.ts +456 -0
- package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +201 -0
- package/templates/docker/src/lib/auth/__tests__/permissions.test.ts +225 -0
- package/templates/docker/src/lib/auth/__tests__/server.test.ts +34 -0
- package/templates/docker/src/lib/auth/__tests__/simple-key.test.ts +176 -0
- package/templates/docker/src/lib/auth/__tests__/types.test.ts +44 -0
- package/templates/docker/src/lib/auth/audit.ts +89 -0
- package/templates/docker/src/lib/auth/byot.ts +158 -0
- package/templates/docker/src/lib/auth/client.ts +35 -0
- package/templates/docker/src/lib/auth/detect.ts +83 -0
- package/templates/docker/src/lib/auth/managed.ts +73 -0
- package/templates/docker/src/lib/auth/middleware.ts +208 -0
- package/templates/docker/src/lib/auth/migrate.ts +111 -0
- package/templates/docker/src/lib/auth/permissions.ts +156 -0
- package/templates/docker/src/lib/auth/server.ts +142 -0
- package/templates/docker/src/lib/auth/simple-key.ts +92 -0
- package/templates/docker/src/lib/auth/types.ts +49 -0
- package/templates/docker/src/lib/config.ts +704 -0
- package/templates/docker/src/lib/conversation-types.ts +29 -0
- package/templates/docker/src/lib/conversations.ts +270 -0
- package/templates/docker/src/lib/db/__tests__/connection.test.ts +69 -0
- package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +141 -0
- package/templates/docker/src/lib/db/__tests__/internal.test.ts +387 -0
- package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +207 -0
- package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
- package/templates/docker/src/lib/db/__tests__/registry.test.ts +595 -0
- package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +339 -0
- package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +217 -0
- package/templates/docker/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
- package/templates/docker/src/lib/db/connection.ts +753 -0
- package/templates/docker/src/lib/db/duckdb.ts +122 -0
- package/templates/docker/src/lib/db/internal.ts +273 -0
- package/templates/docker/src/lib/db/salesforce.ts +342 -0
- package/templates/docker/src/lib/db/source-rate-limit.ts +191 -0
- package/templates/docker/src/lib/errors.ts +154 -0
- package/templates/docker/src/lib/logger.ts +98 -0
- package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
- package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +529 -0
- package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +521 -0
- package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +346 -0
- package/templates/docker/src/lib/plugins/__tests__/tools.test.ts +49 -0
- package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +585 -0
- package/templates/docker/src/lib/plugins/hooks.ts +162 -0
- package/templates/docker/src/lib/plugins/index.ts +9 -0
- package/templates/docker/src/lib/plugins/migrate.ts +309 -0
- package/templates/docker/src/lib/plugins/registry.ts +231 -0
- package/templates/docker/src/lib/plugins/tools.ts +39 -0
- package/templates/docker/src/lib/plugins/wiring.ts +291 -0
- package/templates/docker/src/lib/providers.ts +102 -0
- package/templates/docker/src/lib/rls.ts +321 -0
- package/templates/docker/src/lib/scheduled-task-types.ts +132 -0
- package/templates/docker/src/lib/scheduled-tasks.ts +475 -0
- package/templates/docker/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
- package/templates/docker/src/lib/scheduler/__tests__/engine.test.ts +248 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
- package/templates/docker/src/lib/scheduler/delivery.ts +248 -0
- package/templates/docker/src/lib/scheduler/engine.ts +317 -0
- package/templates/docker/src/lib/scheduler/executor.ts +73 -0
- package/templates/docker/src/lib/scheduler/format-email.ts +109 -0
- package/templates/docker/src/lib/scheduler/format-slack.ts +35 -0
- package/templates/docker/src/lib/scheduler/format-webhook.ts +37 -0
- package/templates/docker/src/lib/scheduler/index.ts +7 -0
- package/templates/docker/src/lib/security.ts +11 -0
- package/templates/docker/src/lib/semantic-index.ts +503 -0
- package/templates/docker/src/lib/semantic.ts +387 -0
- package/templates/docker/src/lib/sidecar-types.ts +16 -0
- package/templates/docker/src/lib/slack/__tests__/api.test.ts +160 -0
- package/templates/docker/src/lib/slack/__tests__/format.test.ts +237 -0
- package/templates/docker/src/lib/slack/__tests__/store.test.ts +188 -0
- package/templates/docker/src/lib/slack/__tests__/threads.test.ts +112 -0
- package/templates/docker/src/lib/slack/__tests__/verify.test.ts +111 -0
- package/templates/docker/src/lib/slack/api.ts +102 -0
- package/templates/docker/src/lib/slack/format.ts +209 -0
- package/templates/docker/src/lib/slack/store.ts +107 -0
- package/templates/docker/src/lib/slack/threads.ts +64 -0
- package/templates/docker/src/lib/slack/verify.ts +71 -0
- package/templates/docker/src/lib/startup.ts +730 -0
- package/templates/docker/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
- package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
- package/templates/docker/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
- package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
- package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
- package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
- package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
- package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
- package/templates/docker/src/lib/tools/__tests__/registry.test.ts +235 -0
- package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
- package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
- package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
- package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
- package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
- package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
- package/templates/docker/src/lib/tools/__tests__/sql.test.ts +1012 -0
- package/templates/docker/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
- package/templates/docker/src/lib/tools/actions/__tests__/email.test.ts +378 -0
- package/templates/docker/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
- package/templates/docker/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
- package/templates/docker/src/lib/tools/actions/audit.ts +47 -0
- package/templates/docker/src/lib/tools/actions/email.ts +191 -0
- package/templates/docker/src/lib/tools/actions/handler.ts +591 -0
- package/templates/docker/src/lib/tools/actions/index.ts +23 -0
- package/templates/docker/src/lib/tools/actions/jira.ts +220 -0
- package/templates/docker/src/lib/tools/explore-nsjail.ts +343 -0
- package/templates/docker/src/lib/tools/explore-sandbox.ts +264 -0
- package/templates/docker/src/lib/tools/explore-sidecar.ts +163 -0
- package/templates/docker/src/lib/tools/explore.ts +379 -0
- package/templates/docker/src/lib/tools/registry.ts +221 -0
- package/templates/docker/src/lib/tools/salesforce.ts +138 -0
- package/templates/docker/src/lib/tools/soql-validation.ts +172 -0
- package/templates/docker/src/lib/tools/sql.ts +680 -0
- package/templates/docker/src/lib/tracing.ts +40 -0
- package/templates/docker/src/lib/utils.ts +6 -0
- package/templates/docker/src/test-setup.ts +38 -0
- package/templates/docker/src/types/vercel-sandbox.d.ts +54 -0
- package/templates/docker/src/ui/components/actions/action-approval-card.tsx +295 -0
- package/templates/docker/src/ui/components/actions/action-status-badge.tsx +50 -0
- package/templates/docker/src/ui/components/admin/admin-layout.tsx +26 -0
- package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +96 -0
- package/templates/docker/src/ui/components/admin/empty-state.tsx +24 -0
- package/templates/docker/src/ui/components/admin/entity-detail.tsx +233 -0
- package/templates/docker/src/ui/components/admin/entity-list.tsx +96 -0
- package/templates/docker/src/ui/components/admin/error-banner.tsx +22 -0
- package/templates/docker/src/ui/components/admin/feature-disabled.tsx +44 -0
- package/templates/docker/src/ui/components/admin/health-badge.tsx +30 -0
- package/templates/docker/src/ui/components/admin/loading-state.tsx +14 -0
- package/templates/docker/src/ui/components/admin/stat-card.tsx +32 -0
- package/templates/docker/src/ui/components/atlas-chat.tsx +370 -0
- package/templates/docker/src/ui/components/chart/chart-detection.ts +261 -0
- package/templates/docker/src/ui/components/chart/result-chart.tsx +375 -0
- package/templates/docker/src/ui/components/chat/api-key-bar.tsx +66 -0
- package/templates/docker/src/ui/components/chat/copy-button.tsx +25 -0
- package/templates/docker/src/ui/components/chat/data-table.tsx +102 -0
- package/templates/docker/src/ui/components/chat/error-banner.tsx +32 -0
- package/templates/docker/src/ui/components/chat/explore-card.tsx +41 -0
- package/templates/docker/src/ui/components/chat/loading-card.tsx +10 -0
- package/templates/docker/src/ui/components/chat/managed-auth-card.tsx +116 -0
- package/templates/docker/src/ui/components/chat/markdown.tsx +72 -0
- package/templates/docker/src/ui/components/chat/sql-block.tsx +30 -0
- package/templates/docker/src/ui/components/chat/sql-result-card.tsx +144 -0
- package/templates/docker/src/ui/components/chat/starter-prompts.ts +6 -0
- package/templates/docker/src/ui/components/chat/tool-part.tsx +40 -0
- package/templates/docker/src/ui/components/chat/typing-indicator.tsx +19 -0
- package/templates/docker/src/ui/components/conversations/conversation-item.tsx +120 -0
- package/templates/docker/src/ui/components/conversations/conversation-list.tsx +66 -0
- package/templates/docker/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
- package/templates/docker/src/ui/components/conversations/delete-confirmation.tsx +27 -0
- package/templates/docker/src/ui/context.tsx +78 -0
- package/templates/docker/src/ui/hooks/use-admin-fetch.ts +104 -0
- package/templates/docker/src/ui/hooks/use-conversations.ts +184 -0
- package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -0
- package/templates/docker/src/ui/lib/action-types.ts +63 -0
- package/templates/docker/src/ui/lib/helpers.ts +104 -0
- package/templates/docker/src/ui/lib/types.ts +145 -0
- package/templates/docker/tsconfig.json +41 -0
- package/templates/docker/vercel.json +3 -0
- package/templates/nextjs-standalone/.env.example +68 -0
- package/templates/nextjs-standalone/bin/__tests__/benchmark.test.ts +598 -0
- package/templates/nextjs-standalone/bin/__tests__/duckdb-ingest.test.ts +171 -0
- package/templates/nextjs-standalone/bin/__tests__/eval.test.ts +434 -0
- package/templates/nextjs-standalone/bin/__tests__/matview-partition.test.ts +615 -0
- package/templates/nextjs-standalone/bin/__tests__/multi-source.test.ts +113 -0
- package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +322 -0
- package/templates/nextjs-standalone/bin/__tests__/profiler-heuristics.test.ts +608 -0
- package/templates/nextjs-standalone/bin/__tests__/query.test.ts +240 -0
- package/templates/nextjs-standalone/bin/__tests__/schema-drift.test.ts +542 -0
- package/templates/nextjs-standalone/bin/__tests__/view-yaml-generation.test.ts +146 -0
- package/templates/nextjs-standalone/bin/atlas.ts +5044 -0
- package/templates/nextjs-standalone/bin/benchmark.ts +695 -0
- package/templates/nextjs-standalone/bin/enrich.ts +559 -0
- package/templates/nextjs-standalone/bin/eval.ts +770 -0
- package/templates/nextjs-standalone/bin/smoke.ts +438 -0
- package/templates/nextjs-standalone/data/.gitkeep +0 -0
- package/templates/nextjs-standalone/data/cybersec.sql +1961 -0
- package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +40 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +170 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +207 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +145 -0
- package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +22 -0
- package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +38 -0
- package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +89 -0
- package/templates/nextjs-standalone/data/demo.sql +373 -0
- package/templates/nextjs-standalone/data/ecommerce.sql +1690 -0
- package/templates/nextjs-standalone/data/init-demo-db.sql +8 -0
- package/templates/nextjs-standalone/docs/deploy.md +390 -0
- package/templates/nextjs-standalone/eslint.config.mjs +18 -0
- package/templates/nextjs-standalone/gitignore +5 -0
- package/templates/nextjs-standalone/next.config.ts +10 -0
- package/templates/nextjs-standalone/package.json +63 -0
- package/templates/nextjs-standalone/postcss.config.mjs +8 -0
- package/templates/nextjs-standalone/semantic/catalog.yml +5 -0
- package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
- package/templates/nextjs-standalone/semantic/glossary.yml +6 -0
- package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/api/__tests__/actions.test.ts +683 -0
- package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +820 -0
- package/templates/nextjs-standalone/src/api/__tests__/auth.test.ts +165 -0
- package/templates/nextjs-standalone/src/api/__tests__/chat.test.ts +376 -0
- package/templates/nextjs-standalone/src/api/__tests__/conversations.test.ts +555 -0
- package/templates/nextjs-standalone/src/api/__tests__/cors.test.ts +135 -0
- package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +169 -0
- package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +261 -0
- package/templates/nextjs-standalone/src/api/__tests__/query.test.ts +891 -0
- package/templates/nextjs-standalone/src/api/__tests__/scheduled-tasks.test.ts +601 -0
- package/templates/nextjs-standalone/src/api/__tests__/slack.test.ts +847 -0
- package/templates/nextjs-standalone/src/api/index.ts +117 -0
- package/templates/nextjs-standalone/src/api/routes/actions.ts +274 -0
- package/templates/nextjs-standalone/src/api/routes/admin.ts +757 -0
- package/templates/nextjs-standalone/src/api/routes/auth.ts +48 -0
- package/templates/nextjs-standalone/src/api/routes/chat.ts +465 -0
- package/templates/nextjs-standalone/src/api/routes/conversations.ts +266 -0
- package/templates/nextjs-standalone/src/api/routes/health.ts +287 -0
- package/templates/nextjs-standalone/src/api/routes/openapi.ts +390 -0
- package/templates/nextjs-standalone/src/api/routes/query.ts +318 -0
- package/templates/nextjs-standalone/src/api/routes/scheduled-tasks.ts +467 -0
- package/templates/nextjs-standalone/src/api/routes/slack.ts +611 -0
- package/templates/nextjs-standalone/src/api/server.ts +226 -0
- package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +33 -0
- package/templates/nextjs-standalone/src/app/error.tsx +24 -0
- package/templates/nextjs-standalone/src/app/global-error.tsx +68 -0
- package/templates/nextjs-standalone/src/app/globals.css +126 -0
- package/templates/nextjs-standalone/src/app/layout.tsx +19 -0
- package/templates/nextjs-standalone/src/app/page.tsx +14 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +437 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +114 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +514 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config-actions.test.ts +166 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +1063 -0
- package/templates/nextjs-standalone/src/lib/__tests__/conversations.test.ts +589 -0
- package/templates/nextjs-standalone/src/lib/__tests__/errors.test.ts +256 -0
- package/templates/nextjs-standalone/src/lib/__tests__/logger.test.ts +200 -0
- package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +99 -0
- package/templates/nextjs-standalone/src/lib/__tests__/rls.test.ts +435 -0
- package/templates/nextjs-standalone/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
- package/templates/nextjs-standalone/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic-index.test.ts +547 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic-multisource.test.ts +544 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic.test.ts +363 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +452 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +465 -0
- package/templates/nextjs-standalone/src/lib/__tests__/tracing.test.ts +28 -0
- package/templates/nextjs-standalone/src/lib/action-types.ts +95 -0
- package/templates/nextjs-standalone/src/lib/agent-query.ts +178 -0
- package/templates/nextjs-standalone/src/lib/agent.ts +505 -0
- package/templates/nextjs-standalone/src/lib/api-url.ts +3 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/audit.test.ts +418 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/byot.test.ts +366 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/detect.test.ts +190 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/managed.test.ts +173 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/middleware.test.ts +456 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +201 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/permissions.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/server.test.ts +34 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/simple-key.test.ts +176 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/types.test.ts +44 -0
- package/templates/nextjs-standalone/src/lib/auth/audit.ts +89 -0
- package/templates/nextjs-standalone/src/lib/auth/byot.ts +158 -0
- package/templates/nextjs-standalone/src/lib/auth/client.ts +23 -0
- package/templates/nextjs-standalone/src/lib/auth/detect.ts +83 -0
- package/templates/nextjs-standalone/src/lib/auth/managed.ts +73 -0
- package/templates/nextjs-standalone/src/lib/auth/middleware.ts +208 -0
- package/templates/nextjs-standalone/src/lib/auth/migrate.ts +111 -0
- package/templates/nextjs-standalone/src/lib/auth/permissions.ts +156 -0
- package/templates/nextjs-standalone/src/lib/auth/server.ts +142 -0
- package/templates/nextjs-standalone/src/lib/auth/simple-key.ts +92 -0
- package/templates/nextjs-standalone/src/lib/auth/types.ts +49 -0
- package/templates/nextjs-standalone/src/lib/config.ts +704 -0
- package/templates/nextjs-standalone/src/lib/conversation-types.ts +29 -0
- package/templates/nextjs-standalone/src/lib/conversations.ts +270 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +69 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +141 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/internal.test.ts +387 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +207 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +595 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +339 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +217 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
- package/templates/nextjs-standalone/src/lib/db/connection.ts +753 -0
- package/templates/nextjs-standalone/src/lib/db/duckdb.ts +122 -0
- package/templates/nextjs-standalone/src/lib/db/internal.ts +273 -0
- package/templates/nextjs-standalone/src/lib/db/salesforce.ts +342 -0
- package/templates/nextjs-standalone/src/lib/db/source-rate-limit.ts +191 -0
- package/templates/nextjs-standalone/src/lib/errors.ts +154 -0
- package/templates/nextjs-standalone/src/lib/logger.ts +98 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +529 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +521 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +346 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/tools.test.ts +49 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +585 -0
- package/templates/nextjs-standalone/src/lib/plugins/hooks.ts +162 -0
- package/templates/nextjs-standalone/src/lib/plugins/index.ts +9 -0
- package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +309 -0
- package/templates/nextjs-standalone/src/lib/plugins/registry.ts +231 -0
- package/templates/nextjs-standalone/src/lib/plugins/tools.ts +39 -0
- package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +291 -0
- package/templates/nextjs-standalone/src/lib/providers.ts +102 -0
- package/templates/nextjs-standalone/src/lib/rls.ts +321 -0
- package/templates/nextjs-standalone/src/lib/scheduled-task-types.ts +132 -0
- package/templates/nextjs-standalone/src/lib/scheduled-tasks.ts +475 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/engine.test.ts +248 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
- package/templates/nextjs-standalone/src/lib/scheduler/delivery.ts +248 -0
- package/templates/nextjs-standalone/src/lib/scheduler/engine.ts +317 -0
- package/templates/nextjs-standalone/src/lib/scheduler/executor.ts +73 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-email.ts +109 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-slack.ts +35 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-webhook.ts +37 -0
- package/templates/nextjs-standalone/src/lib/scheduler/index.ts +7 -0
- package/templates/nextjs-standalone/src/lib/security.ts +11 -0
- package/templates/nextjs-standalone/src/lib/semantic-index.ts +503 -0
- package/templates/nextjs-standalone/src/lib/semantic.ts +387 -0
- package/templates/nextjs-standalone/src/lib/sidecar-types.ts +16 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/api.test.ts +160 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/format.test.ts +237 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/store.test.ts +188 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/threads.test.ts +112 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/verify.test.ts +111 -0
- package/templates/nextjs-standalone/src/lib/slack/api.ts +102 -0
- package/templates/nextjs-standalone/src/lib/slack/format.ts +209 -0
- package/templates/nextjs-standalone/src/lib/slack/store.ts +107 -0
- package/templates/nextjs-standalone/src/lib/slack/threads.ts +64 -0
- package/templates/nextjs-standalone/src/lib/slack/verify.ts +71 -0
- package/templates/nextjs-standalone/src/lib/startup.ts +730 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +235 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +1012 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/email.test.ts +378 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/audit.ts +47 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/email.ts +191 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/handler.ts +591 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/index.ts +23 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/jira.ts +220 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +343 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-sandbox.ts +264 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +163 -0
- package/templates/nextjs-standalone/src/lib/tools/explore.ts +379 -0
- package/templates/nextjs-standalone/src/lib/tools/registry.ts +221 -0
- package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +138 -0
- package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +172 -0
- package/templates/nextjs-standalone/src/lib/tools/sql.ts +680 -0
- package/templates/nextjs-standalone/src/lib/tracing.ts +40 -0
- package/templates/nextjs-standalone/src/lib/utils.ts +6 -0
- package/templates/nextjs-standalone/src/test-setup.ts +38 -0
- package/templates/nextjs-standalone/src/ui/components/actions/action-approval-card.tsx +295 -0
- package/templates/nextjs-standalone/src/ui/components/actions/action-status-badge.tsx +50 -0
- package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +26 -0
- package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +96 -0
- package/templates/nextjs-standalone/src/ui/components/admin/empty-state.tsx +24 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +233 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-list.tsx +96 -0
- package/templates/nextjs-standalone/src/ui/components/admin/error-banner.tsx +22 -0
- package/templates/nextjs-standalone/src/ui/components/admin/feature-disabled.tsx +44 -0
- package/templates/nextjs-standalone/src/ui/components/admin/health-badge.tsx +30 -0
- package/templates/nextjs-standalone/src/ui/components/admin/loading-state.tsx +14 -0
- package/templates/nextjs-standalone/src/ui/components/admin/stat-card.tsx +32 -0
- package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +370 -0
- package/templates/nextjs-standalone/src/ui/components/chart/chart-detection.ts +261 -0
- package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +375 -0
- package/templates/nextjs-standalone/src/ui/components/chat/api-key-bar.tsx +66 -0
- package/templates/nextjs-standalone/src/ui/components/chat/copy-button.tsx +25 -0
- package/templates/nextjs-standalone/src/ui/components/chat/data-table.tsx +102 -0
- package/templates/nextjs-standalone/src/ui/components/chat/error-banner.tsx +32 -0
- package/templates/nextjs-standalone/src/ui/components/chat/explore-card.tsx +41 -0
- package/templates/nextjs-standalone/src/ui/components/chat/loading-card.tsx +10 -0
- package/templates/nextjs-standalone/src/ui/components/chat/managed-auth-card.tsx +116 -0
- package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +72 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +30 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +144 -0
- package/templates/nextjs-standalone/src/ui/components/chat/starter-prompts.ts +6 -0
- package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +40 -0
- package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +19 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +120 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-list.tsx +66 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/delete-confirmation.tsx +27 -0
- package/templates/nextjs-standalone/src/ui/context.tsx +78 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-admin-fetch.ts +104 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +184 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -0
- package/templates/nextjs-standalone/src/ui/lib/action-types.ts +63 -0
- package/templates/nextjs-standalone/src/ui/lib/helpers.ts +104 -0
- package/templates/nextjs-standalone/src/ui/lib/types.ts +145 -0
- package/templates/nextjs-standalone/tsconfig.json +32 -0
- 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
|
+
}
|