@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,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic layer exploration tool.
|
|
3
|
+
*
|
|
4
|
+
* Abstracts the shell backend behind an ExploreBackend interface so the
|
|
5
|
+
* explore tool works across five isolation levels:
|
|
6
|
+
* - sandbox plugin: pluggable explore backend via the Plugin SDK (priority-sorted)
|
|
7
|
+
* - @vercel/sandbox: ephemeral microVM with networkPolicy "deny-all" (Vercel)
|
|
8
|
+
* - nsjail: Linux namespace sandbox (self-hosted Docker)
|
|
9
|
+
* - sidecar: HTTP-isolated container with no secrets (Railway/Render)
|
|
10
|
+
* - just-bash: OverlayFs ensures read-only access; writes stay in memory (dev, or production fallback)
|
|
11
|
+
*
|
|
12
|
+
* Runtime selection priority: sandbox plugin > Vercel sandbox > nsjail (explicit) > sidecar > nsjail (auto-detect) > just-bash.
|
|
13
|
+
* A production warning is logged when falling back to just-bash.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { tool } from "ai";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import * as path from "path";
|
|
19
|
+
import { createLogger } from "@atlas/api/lib/logger";
|
|
20
|
+
import { withSpan } from "@atlas/api/lib/tracing";
|
|
21
|
+
|
|
22
|
+
/** Must match SANDBOX_DEFAULT_PRIORITY in @atlas/plugin-sdk/types. */
|
|
23
|
+
const SANDBOX_DEFAULT_PRIORITY = 60;
|
|
24
|
+
|
|
25
|
+
const log = createLogger("explore");
|
|
26
|
+
|
|
27
|
+
const SEMANTIC_ROOT = path.resolve(process.cwd(), "semantic");
|
|
28
|
+
|
|
29
|
+
// --- Backend interface ---
|
|
30
|
+
|
|
31
|
+
export interface ExecResult {
|
|
32
|
+
stdout: string;
|
|
33
|
+
stderr: string;
|
|
34
|
+
exitCode: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Shell backend for the explore tool.
|
|
39
|
+
*
|
|
40
|
+
* Implementations MUST provide read-only filesystem access scoped to the
|
|
41
|
+
* semantic layer directory. Commands execute within /semantic as the working
|
|
42
|
+
* directory. Writes should be silently discarded or cause errors, never
|
|
43
|
+
* modify the host filesystem.
|
|
44
|
+
*/
|
|
45
|
+
export interface ExploreBackend {
|
|
46
|
+
exec(command: string): Promise<ExecResult>;
|
|
47
|
+
close?(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// --- Self-hosted backend (just-bash) ---
|
|
51
|
+
|
|
52
|
+
async function createBashBackend(
|
|
53
|
+
semanticRoot: string
|
|
54
|
+
): Promise<ExploreBackend> {
|
|
55
|
+
let Bash, OverlayFs;
|
|
56
|
+
try {
|
|
57
|
+
({ Bash, OverlayFs } = await import("just-bash"));
|
|
58
|
+
} catch (err) {
|
|
59
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
60
|
+
log.error({ err: detail }, "Failed to import just-bash");
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Failed to load the just-bash runtime for the explore tool. " +
|
|
63
|
+
"Ensure 'just-bash' is installed ('bun install'). " +
|
|
64
|
+
"If running on Vercel, set ATLAS_RUNTIME=vercel.",
|
|
65
|
+
{ cause: err }
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const overlay = new OverlayFs({
|
|
70
|
+
root: semanticRoot,
|
|
71
|
+
mountPoint: "/semantic",
|
|
72
|
+
});
|
|
73
|
+
const bash = new Bash({
|
|
74
|
+
fs: overlay,
|
|
75
|
+
cwd: "/semantic",
|
|
76
|
+
executionLimits: {
|
|
77
|
+
maxCommandCount: 5000,
|
|
78
|
+
maxLoopIterations: 1000,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
exec: async (command: string) => {
|
|
83
|
+
const result = await bash.exec(command);
|
|
84
|
+
return {
|
|
85
|
+
stdout: result.stdout,
|
|
86
|
+
stderr: result.stderr,
|
|
87
|
+
exitCode: result.exitCode,
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// --- Runtime detection ---
|
|
94
|
+
|
|
95
|
+
function useVercelSandbox(): boolean {
|
|
96
|
+
return process.env.ATLAS_RUNTIME === "vercel" || !!process.env.VERCEL;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let _nsjailAvailable: boolean | null = null;
|
|
100
|
+
|
|
101
|
+
function useNsjail(): boolean {
|
|
102
|
+
if (process.env.ATLAS_SANDBOX === "nsjail") return true;
|
|
103
|
+
if (_nsjailAvailable !== null) return _nsjailAvailable;
|
|
104
|
+
// Auto-detect nsjail on PATH (deferred require to avoid loading module at startup)
|
|
105
|
+
try {
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
107
|
+
const { isNsjailAvailable } = require("./explore-nsjail");
|
|
108
|
+
_nsjailAvailable = isNsjailAvailable();
|
|
109
|
+
} catch (err) {
|
|
110
|
+
if (
|
|
111
|
+
err instanceof Error &&
|
|
112
|
+
"code" in err &&
|
|
113
|
+
(err as NodeJS.ErrnoException).code === "MODULE_NOT_FOUND"
|
|
114
|
+
) {
|
|
115
|
+
_nsjailAvailable = false;
|
|
116
|
+
} else {
|
|
117
|
+
log.error(
|
|
118
|
+
{ error: err instanceof Error ? err.message : String(err) },
|
|
119
|
+
"Unexpected error loading explore-nsjail module",
|
|
120
|
+
);
|
|
121
|
+
_nsjailAvailable = false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return _nsjailAvailable ?? false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function useSidecar(): boolean {
|
|
128
|
+
return !!process.env.ATLAS_SANDBOX_URL;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Track nsjail init failures to avoid infinite retry loops. */
|
|
132
|
+
let _nsjailFailed = false;
|
|
133
|
+
|
|
134
|
+
/** Track sidecar init failures so the health endpoint reports accurately. */
|
|
135
|
+
let _sidecarFailed = false;
|
|
136
|
+
|
|
137
|
+
export type ExploreBackendType = "vercel-sandbox" | "nsjail" | "sidecar" | "just-bash" | "plugin";
|
|
138
|
+
|
|
139
|
+
/** Name of the active sandbox plugin (if any). Set during backend init. */
|
|
140
|
+
let _activeSandboxPluginId: string | null = null;
|
|
141
|
+
|
|
142
|
+
/** Returns the active sandbox plugin id (if any, for health/startup reporting). */
|
|
143
|
+
export function getActiveSandboxPluginId(): string | null {
|
|
144
|
+
return _activeSandboxPluginId;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Returns which explore backend is active (for health endpoint).
|
|
149
|
+
*
|
|
150
|
+
* Plugin detection is lazy — _activeSandboxPluginId is only set after the
|
|
151
|
+
* first explore command triggers getExploreBackend(). Before that, this
|
|
152
|
+
* function falls through to the built-in detection chain.
|
|
153
|
+
*/
|
|
154
|
+
export function getExploreBackendType(): ExploreBackendType {
|
|
155
|
+
if (_activeSandboxPluginId) return "plugin";
|
|
156
|
+
if (useVercelSandbox()) return "vercel-sandbox";
|
|
157
|
+
// Explicit nsjail (ATLAS_SANDBOX=nsjail) — hard-fail if unavailable
|
|
158
|
+
if (process.env.ATLAS_SANDBOX === "nsjail" && !_nsjailFailed) return "nsjail";
|
|
159
|
+
// Sidecar takes priority over nsjail auto-detection (Railway/Render set ATLAS_SANDBOX_URL)
|
|
160
|
+
if (useSidecar() && !_sidecarFailed) return "sidecar";
|
|
161
|
+
// nsjail auto-detect (binary on PATH)
|
|
162
|
+
if (!_nsjailFailed && useNsjail()) return "nsjail";
|
|
163
|
+
return "just-bash";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let backendPromise: Promise<ExploreBackend> | null = null;
|
|
167
|
+
|
|
168
|
+
/** Clear cached backend so the next call recreates it. */
|
|
169
|
+
export function invalidateExploreBackend(): void {
|
|
170
|
+
backendPromise = null;
|
|
171
|
+
_activeSandboxPluginId = null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Permanently mark nsjail as failed and clear the backend cache.
|
|
175
|
+
* Called from explore-nsjail.ts on exit code 109 (sandbox setup failure). */
|
|
176
|
+
export function markNsjailFailed(): void {
|
|
177
|
+
_nsjailFailed = true;
|
|
178
|
+
backendPromise = null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Permanently mark the sidecar as failed so health reports "just-bash".
|
|
182
|
+
* Called from startup.ts when the sidecar health check fails. */
|
|
183
|
+
export function markSidecarFailed(): void {
|
|
184
|
+
_sidecarFailed = true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getExploreBackend(): Promise<ExploreBackend> {
|
|
188
|
+
if (!backendPromise) {
|
|
189
|
+
backendPromise = (async (): Promise<ExploreBackend> => {
|
|
190
|
+
// Priority 0: Sandbox plugins (sorted by priority, highest first)
|
|
191
|
+
// Skipped when ATLAS_SANDBOX=nsjail — operator explicitly wants nsjail only
|
|
192
|
+
if (process.env.ATLAS_SANDBOX !== "nsjail") {
|
|
193
|
+
let sandboxPlugins: Array<{ id: string; [k: string]: unknown }> = [];
|
|
194
|
+
try {
|
|
195
|
+
const { plugins } = await import("@atlas/api/lib/plugins/registry");
|
|
196
|
+
sandboxPlugins = plugins.getByType("sandbox");
|
|
197
|
+
} catch (err) {
|
|
198
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
199
|
+
log.debug({ err: detail }, "Plugin registry not available for sandbox check");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (sandboxPlugins.length > 0) {
|
|
203
|
+
type SandboxShape = { sandbox: { create(root: string): Promise<ExploreBackend> | ExploreBackend; priority?: number } };
|
|
204
|
+
const sorted = [...sandboxPlugins].sort((a, b) => {
|
|
205
|
+
const pa = (a as unknown as SandboxShape).sandbox.priority ?? SANDBOX_DEFAULT_PRIORITY;
|
|
206
|
+
const pb = (b as unknown as SandboxShape).sandbox.priority ?? SANDBOX_DEFAULT_PRIORITY;
|
|
207
|
+
return pb - pa;
|
|
208
|
+
});
|
|
209
|
+
for (const sp of sorted) {
|
|
210
|
+
const sandbox = (sp as unknown as SandboxShape).sandbox;
|
|
211
|
+
try {
|
|
212
|
+
const backend = await sandbox.create(SEMANTIC_ROOT);
|
|
213
|
+
_activeSandboxPluginId = sp.id;
|
|
214
|
+
log.info({ pluginId: sp.id }, "Using sandbox plugin for explore backend");
|
|
215
|
+
return backend;
|
|
216
|
+
} catch (err) {
|
|
217
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
218
|
+
log.error({ pluginId: sp.id, err: detail }, "Sandbox plugin create() failed, trying next");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
log.error({ count: sorted.length }, "All sandbox plugins failed to create a backend");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Priority 1: Vercel Sandbox (Firecracker VM)
|
|
226
|
+
if (useVercelSandbox()) {
|
|
227
|
+
const { createSandboxBackend } = await import("./explore-sandbox");
|
|
228
|
+
return createSandboxBackend(SEMANTIC_ROOT);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Priority 2: nsjail explicit (ATLAS_SANDBOX=nsjail) — hard-fail if init fails
|
|
232
|
+
if (process.env.ATLAS_SANDBOX === "nsjail" && !_nsjailFailed) {
|
|
233
|
+
try {
|
|
234
|
+
const { createNsjailBackend } = await import("./explore-nsjail");
|
|
235
|
+
return await createNsjailBackend(SEMANTIC_ROOT, {
|
|
236
|
+
onInfrastructureError: invalidateExploreBackend,
|
|
237
|
+
onNsjailFailed: markNsjailFailed,
|
|
238
|
+
});
|
|
239
|
+
} catch (err) {
|
|
240
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
241
|
+
throw new Error(
|
|
242
|
+
"nsjail was explicitly requested (ATLAS_SANDBOX=nsjail) but failed to initialize: " +
|
|
243
|
+
detail + ". Fix the nsjail installation or remove ATLAS_SANDBOX to allow fallback.",
|
|
244
|
+
{ cause: err },
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Priority 3: Sidecar service (HTTP-isolated microservice)
|
|
250
|
+
// When ATLAS_SANDBOX_URL is set, sidecar is the intended backend (Railway/Render).
|
|
251
|
+
// Skips nsjail auto-detection entirely — no noisy namespace warnings.
|
|
252
|
+
if (useSidecar()) {
|
|
253
|
+
const { createSidecarBackend } = await import("./explore-sidecar");
|
|
254
|
+
return createSidecarBackend(process.env.ATLAS_SANDBOX_URL!);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Priority 4: nsjail auto-detect (binary on PATH, graceful fallback)
|
|
258
|
+
if (!_nsjailFailed && useNsjail()) {
|
|
259
|
+
try {
|
|
260
|
+
const { createNsjailBackend } = await import("./explore-nsjail");
|
|
261
|
+
return await createNsjailBackend(SEMANTIC_ROOT, {
|
|
262
|
+
onInfrastructureError: invalidateExploreBackend,
|
|
263
|
+
onNsjailFailed: markNsjailFailed,
|
|
264
|
+
});
|
|
265
|
+
} catch (err) {
|
|
266
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
267
|
+
_nsjailFailed = true;
|
|
268
|
+
log.error(
|
|
269
|
+
{ error: detail, fallback: "just-bash" },
|
|
270
|
+
"nsjail backend failed to initialize, falling back to just-bash",
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Priority 5: just-bash (no process isolation)
|
|
276
|
+
if (process.env.NODE_ENV === "production") {
|
|
277
|
+
log.warn(
|
|
278
|
+
"Explore tool running without process isolation. " +
|
|
279
|
+
"Install nsjail, configure a sidecar (ATLAS_SANDBOX_URL), or deploy on Vercel for sandboxed execution. " +
|
|
280
|
+
"See: https://github.com/google/nsjail",
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
return createBashBackend(SEMANTIC_ROOT);
|
|
284
|
+
})().catch((err) => {
|
|
285
|
+
backendPromise = null; // allow retry on next call
|
|
286
|
+
throw err;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return backendPromise;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// --- Tool definition ---
|
|
293
|
+
|
|
294
|
+
export const explore = tool({
|
|
295
|
+
description: `Run bash commands to explore the semantic layer (YAML files describing the data model). The working directory is /semantic.
|
|
296
|
+
|
|
297
|
+
Available commands include: ls, cat, head, tail, grep, find, wc, tree, sort, uniq, cut, awk, sed, and more. Use pipes and flags freely.
|
|
298
|
+
|
|
299
|
+
The semantic directory contains:
|
|
300
|
+
- catalog.yml: Index of all entities and their descriptions
|
|
301
|
+
- entities/*.yml: Default connection table schemas with columns, types, sample values, joins
|
|
302
|
+
- metrics/*.yml: Default connection metric definitions with authoritative SQL
|
|
303
|
+
- glossary.yml: Business term definitions and disambiguation
|
|
304
|
+
- {source}/entities/*.yml: Per-source table schemas (e.g. warehouse/entities/)
|
|
305
|
+
- {source}/metrics/*.yml: Per-source metric definitions
|
|
306
|
+
- {source}/glossary.yml: Source-specific glossary (optional)
|
|
307
|
+
|
|
308
|
+
When multiple data sources are configured, each source has its own subdirectory.
|
|
309
|
+
Entity YAMLs may contain \`cross_source_joins\` describing relationships to tables on other sources — these cannot be SQL-JOINed directly; query each source separately.
|
|
310
|
+
Always start by listing the root directory to see what sources are available.`,
|
|
311
|
+
|
|
312
|
+
inputSchema: z.object({
|
|
313
|
+
command: z
|
|
314
|
+
.string()
|
|
315
|
+
.describe(
|
|
316
|
+
'A bash command to run, e.g. \'cat catalog.yml\', \'grep -r revenue entities/\', \'find . -name "*.yml"\''
|
|
317
|
+
),
|
|
318
|
+
}),
|
|
319
|
+
|
|
320
|
+
execute: async ({ command }) => {
|
|
321
|
+
let backend: ExploreBackend;
|
|
322
|
+
try {
|
|
323
|
+
backend = await getExploreBackend();
|
|
324
|
+
} catch (err) {
|
|
325
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
326
|
+
log.error({ err: detail }, "Explore backend initialization failed");
|
|
327
|
+
return `Error: Explore tool is unavailable — ${detail}`;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
const { dispatchHook, dispatchMutableHook } = await import("@atlas/api/lib/plugins/hooks");
|
|
332
|
+
let execCommand: string;
|
|
333
|
+
try {
|
|
334
|
+
const hookCtx = { command } as const;
|
|
335
|
+
execCommand = await dispatchMutableHook(
|
|
336
|
+
"beforeExplore",
|
|
337
|
+
hookCtx,
|
|
338
|
+
"command",
|
|
339
|
+
);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
342
|
+
log.warn({ err: detail, command }, "Explore command rejected by plugin");
|
|
343
|
+
return `Error: Command rejected by plugin: ${detail}`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// No command re-validation needed — the explore backend (nsjail/sidecar/OverlayFs)
|
|
347
|
+
// enforces read-only scoping regardless of command content
|
|
348
|
+
if (execCommand !== command) {
|
|
349
|
+
log.debug({ original: command, rewritten: execCommand }, "Explore command rewritten by plugin");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const start = performance.now();
|
|
353
|
+
const result = await withSpan(
|
|
354
|
+
"atlas.explore",
|
|
355
|
+
{ command: execCommand.slice(0, 200) },
|
|
356
|
+
() => backend.exec(execCommand),
|
|
357
|
+
);
|
|
358
|
+
const durationMs = Math.round(performance.now() - start);
|
|
359
|
+
|
|
360
|
+
log.debug(
|
|
361
|
+
{ command: execCommand, durationMs, exitCode: result.exitCode },
|
|
362
|
+
"explore command",
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
if (result.exitCode !== 0) {
|
|
366
|
+
return `Error (exit ${result.exitCode}):\n${result.stderr}`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const output = result.stdout || "(no output)";
|
|
370
|
+
await dispatchHook("afterExplore", { command: execCommand, output });
|
|
371
|
+
|
|
372
|
+
return output;
|
|
373
|
+
} catch (err) {
|
|
374
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
375
|
+
log.error({ err: detail, command }, "Explore command failed");
|
|
376
|
+
return `Error: ${detail}`;
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
});
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool registry for the Atlas agent.
|
|
3
|
+
*
|
|
4
|
+
* Decouples tool definitions from the agent loop so tool sets can be
|
|
5
|
+
* composed dynamically. Each tool's {@link AtlasTool.description} is
|
|
6
|
+
* injected into the agent's system prompt via {@link ToolRegistry.describe}.
|
|
7
|
+
* The default registry contains the core tools (explore, executeSQL)
|
|
8
|
+
* with their workflow descriptions extracted from the system prompt.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ToolSet } from "ai";
|
|
12
|
+
import { type AtlasAction, isAction } from "@atlas/api/lib/action-types";
|
|
13
|
+
import { explore } from "./explore";
|
|
14
|
+
import { executeSQL } from "./sql";
|
|
15
|
+
|
|
16
|
+
export type { AtlasAction };
|
|
17
|
+
export { isAction };
|
|
18
|
+
|
|
19
|
+
export interface AtlasTool {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
/** Workflow guidance injected into the system prompt via describe(). */
|
|
22
|
+
readonly description: string;
|
|
23
|
+
readonly tool: ToolSet[string];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class ToolRegistry {
|
|
27
|
+
private tools = new Map<string, AtlasTool>();
|
|
28
|
+
private frozen = false;
|
|
29
|
+
|
|
30
|
+
register(entry: AtlasTool): void {
|
|
31
|
+
if (this.frozen) {
|
|
32
|
+
throw new Error("Cannot register tools on a frozen registry");
|
|
33
|
+
}
|
|
34
|
+
if (!entry.name.trim()) {
|
|
35
|
+
throw new Error("Tool name must not be empty");
|
|
36
|
+
}
|
|
37
|
+
if (!entry.description.trim()) {
|
|
38
|
+
throw new Error("Tool description must not be empty");
|
|
39
|
+
}
|
|
40
|
+
this.tools.set(entry.name, entry);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Freeze the registry, preventing further registrations. */
|
|
44
|
+
freeze(): this {
|
|
45
|
+
this.frozen = true;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get(name: string): AtlasTool | undefined {
|
|
50
|
+
return this.tools.get(name);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getAll(): ToolSet {
|
|
54
|
+
const result: ToolSet = {};
|
|
55
|
+
for (const [name, entry] of this.tools) {
|
|
56
|
+
result[name] = entry.tool;
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Concatenate all tool descriptions. Output order follows registration order. */
|
|
62
|
+
describe(): string {
|
|
63
|
+
return Array.from(this.tools.values())
|
|
64
|
+
.map((entry) => entry.description)
|
|
65
|
+
.join("\n\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Iterate over all registered tool entries. */
|
|
69
|
+
entries(): IterableIterator<[string, AtlasTool]> {
|
|
70
|
+
return this.tools.entries();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get size(): number {
|
|
74
|
+
return this.tools.size;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Create a new registry by merging one or more registries on top of a base.
|
|
79
|
+
* Entries in later registries take precedence. The returned registry is
|
|
80
|
+
* **unfrozen** — the caller should freeze it when ready.
|
|
81
|
+
*/
|
|
82
|
+
static merge(base: ToolRegistry, ...others: ToolRegistry[]): ToolRegistry {
|
|
83
|
+
const merged = new ToolRegistry();
|
|
84
|
+
for (const [, entry] of base.entries()) {
|
|
85
|
+
merged.register(entry);
|
|
86
|
+
}
|
|
87
|
+
for (const other of others) {
|
|
88
|
+
for (const [name, entry] of other.entries()) {
|
|
89
|
+
if (merged.get(name)) continue; // base takes precedence
|
|
90
|
+
merged.register(entry);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return merged;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Return all registered tools that are actions (have actionType metadata). */
|
|
97
|
+
getActions(): AtlasAction[] {
|
|
98
|
+
return Array.from(this.tools.values()).filter(isAction) as AtlasAction[];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Check that all required credentials for registered actions are present
|
|
103
|
+
* in the environment. Returns an array of `{ action, missing }` for each
|
|
104
|
+
* action with missing credentials (empty array means all good).
|
|
105
|
+
*/
|
|
106
|
+
validateActionCredentials(): { action: string; missing: string[] }[] {
|
|
107
|
+
const results: { action: string; missing: string[] }[] = [];
|
|
108
|
+
for (const action of this.getActions()) {
|
|
109
|
+
const missing = action.requiredCredentials.filter(
|
|
110
|
+
(key) => !process.env[key],
|
|
111
|
+
);
|
|
112
|
+
if (missing.length > 0) {
|
|
113
|
+
results.push({ action: action.name, missing });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// --- Workflow descriptions (extracted from the system prompt) ---
|
|
121
|
+
|
|
122
|
+
const EXPLORE_DESCRIPTION = `### 2. Explore the Semantic Layer
|
|
123
|
+
Use the explore tool to run bash commands against the semantic/ directory:
|
|
124
|
+
- Start with \`cat catalog.yml\` to find relevant entities
|
|
125
|
+
- Read entity schemas: \`cat entities/companies.yml\`, \`head -30 entities/deals.yml\`
|
|
126
|
+
- Search across files: \`grep -r "revenue" entities/\`, \`grep -rl "join" entities/\`
|
|
127
|
+
- List and discover files: \`ls entities/\`, \`find . -name "*.yml"\`, \`tree\`
|
|
128
|
+
- Check metrics/*.yml for canonical metric definitions — use these SQL patterns exactly
|
|
129
|
+
- Combine commands with pipes: \`grep -r "column" entities/ | sort\`, \`cat entities/deals.yml | grep -A5 "measures"\`
|
|
130
|
+
- Never guess column names. Always verify against the schema.`;
|
|
131
|
+
|
|
132
|
+
const EXECUTE_SQL_DESCRIPTION = `### 3. Write and Execute SQL
|
|
133
|
+
Use the executeSQL tool to query the database:
|
|
134
|
+
- Use exact column names from the entity schemas
|
|
135
|
+
- If a canonical metric definition exists, use that SQL — do not improvise
|
|
136
|
+
- Include appropriate filters, groupings, and ordering
|
|
137
|
+
- If a query fails, read the error, fix the SQL, and retry (max 2 retries, never retry the same SQL)`;
|
|
138
|
+
|
|
139
|
+
const QUERY_SALESFORCE_DESCRIPTION = `### 3b. Query Salesforce (SOQL)
|
|
140
|
+
Use the querySalesforce tool to query Salesforce objects:
|
|
141
|
+
- SOQL uses SELECT ... FROM ObjectName syntax (no schema.table)
|
|
142
|
+
- Use relationship queries for related objects (e.g. SELECT Account.Name FROM Contact)
|
|
143
|
+
- SOQL does NOT support JOINs — use parent-to-child or child-to-parent relationship queries
|
|
144
|
+
- Date literals: TODAY, YESTERDAY, LAST_WEEK, THIS_MONTH, LAST_N_DAYS:30
|
|
145
|
+
- Use exact field API names from the entity schemas — never guess
|
|
146
|
+
- If a query fails, read the error, fix the SOQL, and retry (max 2 retries)`;
|
|
147
|
+
|
|
148
|
+
// --- Default registry ---
|
|
149
|
+
|
|
150
|
+
const defaultRegistry = new ToolRegistry();
|
|
151
|
+
|
|
152
|
+
defaultRegistry.register({
|
|
153
|
+
name: "explore",
|
|
154
|
+
description: EXPLORE_DESCRIPTION,
|
|
155
|
+
tool: explore,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
defaultRegistry.register({
|
|
159
|
+
name: "executeSQL",
|
|
160
|
+
description: EXECUTE_SQL_DESCRIPTION,
|
|
161
|
+
tool: executeSQL,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
defaultRegistry.freeze();
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Build a dynamic ToolRegistry with optional Salesforce and action support.
|
|
168
|
+
*
|
|
169
|
+
* When `includeSalesforce` is true, the `querySalesforce` tool is added
|
|
170
|
+
* alongside the core tools.
|
|
171
|
+
* When `includeActions` is true, the action tools (createJiraTicket,
|
|
172
|
+
* sendEmailReport) are added.
|
|
173
|
+
*/
|
|
174
|
+
export async function buildRegistry(options?: {
|
|
175
|
+
includeSalesforce?: boolean;
|
|
176
|
+
includeActions?: boolean;
|
|
177
|
+
}): Promise<ToolRegistry> {
|
|
178
|
+
const registry = new ToolRegistry();
|
|
179
|
+
|
|
180
|
+
registry.register({
|
|
181
|
+
name: "explore",
|
|
182
|
+
description: EXPLORE_DESCRIPTION,
|
|
183
|
+
tool: explore,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
registry.register({
|
|
187
|
+
name: "executeSQL",
|
|
188
|
+
description: EXECUTE_SQL_DESCRIPTION,
|
|
189
|
+
tool: executeSQL,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
if (options?.includeSalesforce) {
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
194
|
+
const { querySalesforce } = require("./salesforce");
|
|
195
|
+
registry.register({
|
|
196
|
+
name: "querySalesforce",
|
|
197
|
+
description: QUERY_SALESFORCE_DESCRIPTION,
|
|
198
|
+
tool: querySalesforce,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (options?.includeActions) {
|
|
203
|
+
try {
|
|
204
|
+
const { createJiraTicket, sendEmailReport } = await import("./actions");
|
|
205
|
+
registry.register(createJiraTicket as unknown as AtlasTool);
|
|
206
|
+
registry.register(sendEmailReport as unknown as AtlasTool);
|
|
207
|
+
} catch (err) {
|
|
208
|
+
const { createLogger } = await import("@atlas/api/lib/logger");
|
|
209
|
+
const actionLog = createLogger("registry");
|
|
210
|
+
actionLog.error(
|
|
211
|
+
{ err: err instanceof Error ? err : new Error(String(err)) },
|
|
212
|
+
"Failed to load action tools — JIRA and email actions will be unavailable",
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
registry.freeze();
|
|
218
|
+
return registry;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export { defaultRegistry };
|