slackhive 0.1.37 → 0.1.39
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/.dockerignore +14 -0
- package/.env.example +44 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +65 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +38 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +27 -0
- package/.github/dependabot.yml +20 -0
- package/.github/workflows/audit.yml +149 -0
- package/.github/workflows/ci.yml +135 -0
- package/CHANGELOG.md +52 -0
- package/CODE_OF_CONDUCT.md +37 -0
- package/CONTRIBUTING.md +204 -0
- package/LICENSE +21 -0
- package/README.md +19 -0
- package/SECURITY.md +47 -0
- package/apps/runner/Dockerfile +33 -0
- package/apps/runner/dist/__tests__/channel-restrictions.test.d.ts +8 -0
- package/apps/runner/dist/__tests__/channel-restrictions.test.js +63 -0
- package/apps/runner/dist/__tests__/channel-restrictions.test.js.map +1 -0
- package/apps/runner/dist/__tests__/claude-handler-resolve.test.d.ts +20 -0
- package/apps/runner/dist/__tests__/claude-handler-resolve.test.js +178 -0
- package/apps/runner/dist/__tests__/claude-handler-resolve.test.js.map +1 -0
- package/apps/runner/dist/__tests__/compile-claude-md.test.d.ts +13 -0
- package/apps/runner/dist/__tests__/compile-claude-md.test.js +144 -0
- package/apps/runner/dist/__tests__/compile-claude-md.test.js.map +1 -0
- package/apps/runner/dist/__tests__/memory-sync.test.d.ts +11 -0
- package/apps/runner/dist/__tests__/memory-sync.test.js +56 -0
- package/apps/runner/dist/__tests__/memory-sync.test.js.map +1 -0
- package/apps/runner/dist/__tests__/slack-file-support.test.d.ts +9 -0
- package/apps/runner/dist/__tests__/slack-file-support.test.js +271 -0
- package/apps/runner/dist/__tests__/slack-file-support.test.js.map +1 -0
- package/apps/runner/dist/__tests__/slack-formatting.test.d.ts +12 -0
- package/apps/runner/dist/__tests__/slack-formatting.test.js +400 -0
- package/apps/runner/dist/__tests__/slack-formatting.test.js.map +1 -0
- package/apps/runner/dist/__tests__/thread-context.test.d.ts +12 -0
- package/apps/runner/dist/__tests__/thread-context.test.js +182 -0
- package/apps/runner/dist/__tests__/thread-context.test.js.map +1 -0
- package/apps/runner/dist/agent-runner.d.ts +118 -0
- package/apps/runner/dist/agent-runner.js +352 -0
- package/apps/runner/dist/agent-runner.js.map +1 -0
- package/apps/runner/dist/claude-handler.d.ts +122 -0
- package/apps/runner/dist/claude-handler.js +402 -0
- package/apps/runner/dist/claude-handler.js.map +1 -0
- package/apps/runner/dist/compile-claude-md.d.ts +59 -0
- package/apps/runner/dist/compile-claude-md.js +291 -0
- package/apps/runner/dist/compile-claude-md.js.map +1 -0
- package/apps/runner/dist/correction-handler.d.ts +46 -0
- package/apps/runner/dist/correction-handler.js +162 -0
- package/apps/runner/dist/correction-handler.js.map +1 -0
- package/apps/runner/dist/correction-manager.d.ts +53 -0
- package/apps/runner/dist/correction-manager.js +241 -0
- package/apps/runner/dist/correction-manager.js.map +1 -0
- package/apps/runner/dist/db.d.ts +193 -0
- package/apps/runner/dist/db.js +492 -0
- package/apps/runner/dist/db.js.map +1 -0
- package/apps/runner/dist/index.d.ts +9 -0
- package/apps/runner/dist/index.js +43 -0
- package/apps/runner/dist/index.js.map +1 -0
- package/apps/runner/dist/job-scheduler.d.ts +57 -0
- package/apps/runner/dist/job-scheduler.js +150 -0
- package/apps/runner/dist/job-scheduler.js.map +1 -0
- package/apps/runner/dist/logger.d.ts +32 -0
- package/apps/runner/dist/logger.js +52 -0
- package/apps/runner/dist/logger.js.map +1 -0
- package/apps/runner/dist/mcp-process-manager.d.ts +38 -0
- package/apps/runner/dist/mcp-process-manager.js +189 -0
- package/apps/runner/dist/mcp-process-manager.js.map +1 -0
- package/apps/runner/dist/memory-mcp.d.ts +14 -0
- package/apps/runner/dist/memory-mcp.js +88 -0
- package/apps/runner/dist/memory-mcp.js.map +1 -0
- package/apps/runner/dist/memory-watcher.d.ts +78 -0
- package/apps/runner/dist/memory-watcher.js +220 -0
- package/apps/runner/dist/memory-watcher.js.map +1 -0
- package/apps/runner/dist/slack-handler.d.ts +120 -0
- package/apps/runner/dist/slack-handler.js +843 -0
- package/apps/runner/dist/slack-handler.js.map +1 -0
- package/apps/runner/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/apps/runner/package.json +42 -0
- package/apps/runner/src/__tests__/channel-restrictions.test.ts +75 -0
- package/apps/runner/src/__tests__/claude-handler-resolve.test.ts +160 -0
- package/apps/runner/src/__tests__/compile-claude-md.test.ts +139 -0
- package/apps/runner/src/__tests__/memory-sync.test.ts +59 -0
- package/apps/runner/src/__tests__/slack-file-support.test.ts +376 -0
- package/apps/runner/src/__tests__/slack-formatting.test.ts +495 -0
- package/apps/runner/src/__tests__/thread-context.test.ts +215 -0
- package/apps/runner/src/agent-runner.ts +397 -0
- package/apps/runner/src/claude-handler.ts +475 -0
- package/apps/runner/src/compile-claude-md.ts +283 -0
- package/apps/runner/src/correction-handler.ts +191 -0
- package/apps/runner/src/correction-manager.ts +285 -0
- package/apps/runner/src/db.ts +604 -0
- package/apps/runner/src/index.ts +46 -0
- package/apps/runner/src/job-scheduler.ts +165 -0
- package/apps/runner/src/logger.ts +49 -0
- package/apps/runner/src/mcp-process-manager.ts +195 -0
- package/apps/runner/src/memory-mcp.ts +85 -0
- package/apps/runner/src/memory-watcher.ts +215 -0
- package/apps/runner/src/slack-handler.ts +929 -0
- package/apps/runner/tsconfig.json +17 -0
- package/apps/runner/vitest.config.mts +17 -0
- package/apps/web/.eslintrc.json +3 -0
- package/apps/web/.next/app-build-manifest.json +323 -0
- package/apps/web/.next/app-path-routes-manifest.json +46 -0
- package/apps/web/.next/build-manifest.json +33 -0
- package/apps/web/.next/cache/.previewinfo +1 -0
- package/apps/web/.next/cache/.rscinfo +1 -0
- package/apps/web/.next/cache/webpack/client-production/0.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/1.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/2.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/3.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/4.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/index.pack +0 -0
- package/apps/web/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/apps/web/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/apps/web/.next/cache/webpack/edge-server-production/1.pack +0 -0
- package/apps/web/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/apps/web/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
- package/apps/web/.next/cache/webpack/server-production/0.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/1.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/2.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/index.pack +0 -0
- package/apps/web/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/apps/web/.next/diagnostics/build-diagnostics.json +6 -0
- package/apps/web/.next/diagnostics/framework.json +1 -0
- package/apps/web/.next/package.json +1 -0
- package/apps/web/.next/react-loadable-manifest.json +1 -0
- package/apps/web/.next/server/app/_not-found/page.js +2 -0
- package/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/agents/[slug]/page.js +4 -0
- package/apps/web/.next/server/app/agents/[slug]/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/agents/[slug]/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/agents/new/page.js +2 -0
- package/apps/web/.next/server/app/agents/new/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/agents/new/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/access/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/access/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/access/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/claude-md/route.js +6 -0
- package/apps/web/.next/server/app/api/agents/[id]/claude-md/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/claude-md/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/logs/route.js +3 -0
- package/apps/web/.next/server/app/api/agents/[id]/logs/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/logs/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/manifest/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/manifest/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/manifest/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/mcps/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/mcps/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/mcps/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/memories/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/permissions/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/permissions/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/permissions/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/reload/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/reload/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/reload/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/restrictions/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/restrictions/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/restrictions/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/route.js +33 -0
- package/apps/web/.next/server/app/api/agents/[id]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/skills/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/slack-info/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/slack-info/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/slack-info/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/snapshots/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/start/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/start/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/start/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/stop/route.js +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/stop/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/[id]/stop/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/agents/route.js +91 -0
- package/apps/web/.next/server/app/api/agents/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/agents/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/auth/login/route.js +1 -0
- package/apps/web/.next/server/app/api/auth/login/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/auth/logout/route.js +1 -0
- package/apps/web/.next/server/app/api/auth/logout/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/auth/me/route.js +1 -0
- package/apps/web/.next/server/app/api/auth/me/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/auth/users/[id]/route.js +1 -0
- package/apps/web/.next/server/app/api/auth/users/[id]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/auth/users/[id]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/auth/users/route.js +1 -0
- package/apps/web/.next/server/app/api/auth/users/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/auth/users/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/env-vars/[key]/route.js +1 -0
- package/apps/web/.next/server/app/api/env-vars/[key]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/env-vars/[key]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/env-vars/route.js +1 -0
- package/apps/web/.next/server/app/api/env-vars/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/env-vars/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/route.js +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/runs/route.js +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/runs/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/jobs/[id]/runs/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/jobs/route.js +1 -0
- package/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/jobs/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/route.js +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/test/route.js +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/test/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/mcps/[id]/test/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/mcps/route.js +1 -0
- package/apps/web/.next/server/app/api/mcps/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/mcps/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/api/settings/route.js +1 -0
- package/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/api/settings/route_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/icon.svg/route.js +1 -0
- package/apps/web/.next/server/app/icon.svg/route.js.nft.json +1 -0
- package/apps/web/.next/server/app/jobs/page.js +2 -0
- package/apps/web/.next/server/app/jobs/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/jobs/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/login/page.js +2 -0
- package/apps/web/.next/server/app/login/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/login/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/page.js +2 -0
- package/apps/web/.next/server/app/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/settings/env-vars/page.js +2 -0
- package/apps/web/.next/server/app/settings/env-vars/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/settings/env-vars/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/settings/mcps/page.js +2 -0
- package/apps/web/.next/server/app/settings/mcps/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/settings/mcps/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app/settings/page.js +2 -0
- package/apps/web/.next/server/app/settings/page.js.nft.json +1 -0
- package/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -0
- package/apps/web/.next/server/app-paths-manifest.json +46 -0
- package/apps/web/.next/server/chunks/1157.js +9 -0
- package/apps/web/.next/server/chunks/2287.js +1 -0
- package/apps/web/.next/server/chunks/3444.js +1 -0
- package/apps/web/.next/server/chunks/383.js +6 -0
- package/apps/web/.next/server/chunks/4012.js +58 -0
- package/apps/web/.next/server/chunks/6791.js +1 -0
- package/apps/web/.next/server/chunks/7171.js +1 -0
- package/apps/web/.next/server/chunks/8819.js +22 -0
- package/apps/web/.next/server/edge-runtime-webpack.js +2 -0
- package/apps/web/.next/server/edge-runtime-webpack.js.map +1 -0
- package/apps/web/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/apps/web/.next/server/middleware-build-manifest.js +1 -0
- package/apps/web/.next/server/middleware-manifest.json +32 -0
- package/apps/web/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/apps/web/.next/server/next-font-manifest.js +1 -0
- package/apps/web/.next/server/next-font-manifest.json +1 -0
- package/apps/web/.next/server/pages/_app.js +1 -0
- package/apps/web/.next/server/pages/_app.js.nft.json +1 -0
- package/apps/web/.next/server/pages/_document.js +1 -0
- package/apps/web/.next/server/pages/_document.js.nft.json +1 -0
- package/apps/web/.next/server/pages/_error.js +19 -0
- package/apps/web/.next/server/pages/_error.js.nft.json +1 -0
- package/apps/web/.next/server/pages-manifest.json +5 -0
- package/apps/web/.next/server/server-reference-manifest.js +1 -0
- package/apps/web/.next/server/server-reference-manifest.json +1 -0
- package/apps/web/.next/server/src/middleware.js +14 -0
- package/apps/web/.next/server/src/middleware.js.map +1 -0
- package/apps/web/.next/server/webpack-runtime.js +1 -0
- package/apps/web/.next/static/chunks/18-90b700ea37b686a2.js +1 -0
- package/apps/web/.next/static/chunks/87c73c54-24122e7b92478d00.js +1 -0
- package/apps/web/.next/static/chunks/9664-af80478aa73ba424.js +1 -0
- package/apps/web/.next/static/chunks/app/_not-found/page-b9cee17ed89ca24a.js +1 -0
- package/apps/web/.next/static/chunks/app/agents/[slug]/page-18369fc3fe1a9a7b.js +1 -0
- package/apps/web/.next/static/chunks/app/agents/new/page-bf11cf8901c7e2cd.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/access/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/claude-md/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/logs/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/manifest/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/mcps/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/memories/[memId]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/memories/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/permissions/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/reload/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/restrictions/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/skills/[skillId]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/skills/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/slack-info/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/[sid]/restore/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/[sid]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/start/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/[id]/stop/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/agents/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/auth/login/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/auth/logout/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/auth/me/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/auth/users/[id]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/auth/users/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/env-vars/[key]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/env-vars/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/jobs/[id]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/jobs/[id]/runs/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/jobs/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/mcps/[id]/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/mcps/[id]/test/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/mcps/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/api/settings/route-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/jobs/page-f5aa89a47c50efd8.js +1 -0
- package/apps/web/.next/static/chunks/app/layout-2079f4964aa7314e.js +1 -0
- package/apps/web/.next/static/chunks/app/login/layout-07f0f73ac9839899.js +1 -0
- package/apps/web/.next/static/chunks/app/login/page-aa259283dc38e8f9.js +1 -0
- package/apps/web/.next/static/chunks/app/page-e83437b608104dff.js +1 -0
- package/apps/web/.next/static/chunks/app/settings/env-vars/page-06479dbdfb78b76b.js +1 -0
- package/apps/web/.next/static/chunks/app/settings/mcps/page-75650686ed6490c7.js +1 -0
- package/apps/web/.next/static/chunks/app/settings/page-e1e62fc41ff6cddd.js +1 -0
- package/apps/web/.next/static/chunks/framework-811407f832a33072.js +1 -0
- package/apps/web/.next/static/chunks/main-3f1cddbdd67b1546.js +1 -0
- package/apps/web/.next/static/chunks/main-app-cebd8a6a5ccbf72d.js +1 -0
- package/apps/web/.next/static/chunks/pages/_app-50fa07b56b2d29ac.js +1 -0
- package/apps/web/.next/static/chunks/pages/_error-fed8688bdd23f211.js +1 -0
- package/apps/web/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/apps/web/.next/static/chunks/webpack-6c05566dba553c97.js +1 -0
- package/apps/web/.next/static/css/15371687405525e2.css +5 -0
- package/apps/web/.next/static/ikfNbLhuw7jntn35bz0lk/_buildManifest.js +1 -0
- package/apps/web/.next/static/ikfNbLhuw7jntn35bz0lk/_ssgManifest.js +1 -0
- package/apps/web/.next/trace +5 -0
- package/apps/web/.next/types/app/agents/[slug]/page.ts +84 -0
- package/apps/web/.next/types/app/agents/new/page.ts +84 -0
- package/apps/web/.next/types/app/api/agents/[id]/access/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/claude-md/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/logs/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/manifest/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/mcps/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/memories/[memId]/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/memories/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/permissions/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/reload/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/restrictions/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/skills/[skillId]/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/skills/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/slack-info/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/snapshots/[sid]/restore/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/snapshots/[sid]/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/snapshots/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/start/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/[id]/stop/route.ts +347 -0
- package/apps/web/.next/types/app/api/agents/route.ts +347 -0
- package/apps/web/.next/types/app/api/auth/login/route.ts +347 -0
- package/apps/web/.next/types/app/api/auth/logout/route.ts +347 -0
- package/apps/web/.next/types/app/api/auth/me/route.ts +347 -0
- package/apps/web/.next/types/app/api/auth/users/[id]/route.ts +347 -0
- package/apps/web/.next/types/app/api/auth/users/route.ts +347 -0
- package/apps/web/.next/types/app/api/env-vars/[key]/route.ts +347 -0
- package/apps/web/.next/types/app/api/env-vars/route.ts +347 -0
- package/apps/web/.next/types/app/api/jobs/[id]/route.ts +347 -0
- package/apps/web/.next/types/app/api/jobs/[id]/runs/route.ts +347 -0
- package/apps/web/.next/types/app/api/jobs/route.ts +347 -0
- package/apps/web/.next/types/app/api/mcps/[id]/route.ts +347 -0
- package/apps/web/.next/types/app/api/mcps/[id]/test/route.ts +347 -0
- package/apps/web/.next/types/app/api/mcps/route.ts +347 -0
- package/apps/web/.next/types/app/api/settings/route.ts +347 -0
- package/apps/web/.next/types/app/jobs/page.ts +84 -0
- package/apps/web/.next/types/app/login/layout.ts +84 -0
- package/apps/web/.next/types/app/login/page.ts +84 -0
- package/apps/web/.next/types/app/page.ts +84 -0
- package/apps/web/.next/types/app/settings/env-vars/page.ts +84 -0
- package/apps/web/.next/types/app/settings/mcps/page.ts +84 -0
- package/apps/web/.next/types/app/settings/page.ts +84 -0
- package/apps/web/.next/types/cache-life.d.ts +141 -0
- package/apps/web/.next/types/package.json +1 -0
- package/apps/web/.next/types/routes.d.ts +114 -0
- package/apps/web/.next/types/validator.ts +448 -0
- package/apps/web/Dockerfile +37 -0
- package/apps/web/next-env.d.ts +6 -0
- package/apps/web/next.config.js +6 -0
- package/apps/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/apps/web/package.json +48 -0
- package/apps/web/postcss.config.js +3 -0
- package/apps/web/public/logo.svg +17 -0
- package/apps/web/src/app/agents/[slug]/page.tsx +2235 -0
- package/apps/web/src/app/agents/new/page.tsx +1161 -0
- package/apps/web/src/app/api/agents/[id]/access/route.ts +76 -0
- package/apps/web/src/app/api/agents/[id]/claude-md/route.ts +111 -0
- package/apps/web/src/app/api/agents/[id]/logs/route.ts +84 -0
- package/apps/web/src/app/api/agents/[id]/manifest/route.ts +32 -0
- package/apps/web/src/app/api/agents/[id]/mcps/route.ts +73 -0
- package/apps/web/src/app/api/agents/[id]/memories/[memId]/route.ts +31 -0
- package/apps/web/src/app/api/agents/[id]/memories/route.ts +56 -0
- package/apps/web/src/app/api/agents/[id]/permissions/route.ts +74 -0
- package/apps/web/src/app/api/agents/[id]/reload/route.ts +33 -0
- package/apps/web/src/app/api/agents/[id]/restrictions/route.ts +85 -0
- package/apps/web/src/app/api/agents/[id]/route.ts +81 -0
- package/apps/web/src/app/api/agents/[id]/skills/[skillId]/route.ts +52 -0
- package/apps/web/src/app/api/agents/[id]/skills/route.ts +80 -0
- package/apps/web/src/app/api/agents/[id]/slack-info/route.ts +38 -0
- package/apps/web/src/app/api/agents/[id]/snapshots/[sid]/restore/route.ts +61 -0
- package/apps/web/src/app/api/agents/[id]/snapshots/[sid]/route.ts +53 -0
- package/apps/web/src/app/api/agents/[id]/snapshots/route.ts +84 -0
- package/apps/web/src/app/api/agents/[id]/start/route.ts +35 -0
- package/apps/web/src/app/api/agents/[id]/stop/route.ts +35 -0
- package/apps/web/src/app/api/agents/route.ts +99 -0
- package/apps/web/src/app/api/auth/login/route.ts +39 -0
- package/apps/web/src/app/api/auth/logout/route.ts +21 -0
- package/apps/web/src/app/api/auth/me/route.ts +24 -0
- package/apps/web/src/app/api/auth/users/[id]/route.ts +48 -0
- package/apps/web/src/app/api/auth/users/route.ts +63 -0
- package/apps/web/src/app/api/env-vars/[key]/route.ts +66 -0
- package/apps/web/src/app/api/env-vars/route.ts +59 -0
- package/apps/web/src/app/api/jobs/[id]/route.ts +51 -0
- package/apps/web/src/app/api/jobs/[id]/runs/route.ts +24 -0
- package/apps/web/src/app/api/jobs/route.ts +42 -0
- package/apps/web/src/app/api/mcps/[id]/route.ts +60 -0
- package/apps/web/src/app/api/mcps/[id]/test/route.ts +195 -0
- package/apps/web/src/app/api/mcps/route.ts +72 -0
- package/apps/web/src/app/api/settings/route.ts +42 -0
- package/apps/web/src/app/globals.css +124 -0
- package/apps/web/src/app/icon.svg +17 -0
- package/apps/web/src/app/jobs/page.tsx +543 -0
- package/apps/web/src/app/layout-shell.tsx +89 -0
- package/apps/web/src/app/layout.tsx +18 -0
- package/apps/web/src/app/login/layout.tsx +9 -0
- package/apps/web/src/app/login/page.tsx +150 -0
- package/apps/web/src/app/page.tsx +573 -0
- package/apps/web/src/app/settings/env-vars/page.tsx +216 -0
- package/apps/web/src/app/settings/mcps/page.tsx +763 -0
- package/apps/web/src/app/settings/page.tsx +528 -0
- package/apps/web/src/app/sidebar.tsx +345 -0
- package/apps/web/src/lib/__tests__/api-guard.test.ts +189 -0
- package/apps/web/src/lib/__tests__/auth.test.ts +262 -0
- package/apps/web/src/lib/__tests__/boss-registry.test.ts +323 -0
- package/apps/web/src/lib/__tests__/compile.test.ts +161 -0
- package/apps/web/src/lib/__tests__/db-agent-hierarchy.test.ts +136 -0
- package/apps/web/src/lib/__tests__/db-env-vars.test.ts +216 -0
- package/apps/web/src/lib/__tests__/db-restrictions.test.ts +117 -0
- package/apps/web/src/lib/__tests__/db.integration.test.ts +271 -0
- package/apps/web/src/lib/__tests__/diff.test.ts +102 -0
- package/apps/web/src/lib/__tests__/mcp-mask.test.ts +274 -0
- package/apps/web/src/lib/__tests__/skill-templates.test.ts +237 -0
- package/apps/web/src/lib/__tests__/slack-manifest.test.ts +105 -0
- package/apps/web/src/lib/api-guard.ts +68 -0
- package/apps/web/src/lib/auth-context.tsx +71 -0
- package/apps/web/src/lib/auth.ts +128 -0
- package/apps/web/src/lib/boss-registry.ts +90 -0
- package/apps/web/src/lib/compile.ts +51 -0
- package/apps/web/src/lib/db.ts +1196 -0
- package/apps/web/src/lib/diff.ts +43 -0
- package/apps/web/src/lib/mcp-mask.ts +91 -0
- package/apps/web/src/lib/portal.tsx +23 -0
- package/apps/web/src/lib/skill-templates.ts +148 -0
- package/apps/web/src/lib/slack-manifest.ts +85 -0
- package/apps/web/src/middleware.ts +68 -0
- package/apps/web/tailwind.config.js +6 -0
- package/apps/web/tsconfig.json +23 -0
- package/apps/web/vitest.config.mts +21 -0
- package/cli/.claude/settings.local.json +6 -0
- package/cli/README.md +281 -0
- package/cli/node_modules/.package-lock.json +427 -0
- package/cli/node_modules/commander/LICENSE +22 -0
- package/cli/node_modules/commander/Readme.md +1157 -0
- package/cli/node_modules/commander/esm.mjs +16 -0
- package/cli/node_modules/commander/index.js +24 -0
- package/cli/node_modules/commander/lib/argument.js +149 -0
- package/cli/node_modules/commander/lib/command.js +2509 -0
- package/cli/node_modules/commander/lib/error.js +39 -0
- package/cli/node_modules/commander/lib/help.js +520 -0
- package/cli/node_modules/commander/lib/option.js +330 -0
- package/cli/node_modules/commander/lib/suggestSimilar.js +101 -0
- package/cli/node_modules/commander/package-support.json +16 -0
- package/cli/node_modules/commander/package.json +84 -0
- package/cli/node_modules/commander/typings/esm.d.mts +3 -0
- package/cli/node_modules/commander/typings/index.d.ts +969 -0
- package/cli/package-lock.json +449 -0
- package/cli/package.json +44 -0
- package/cli/src/commands/init.ts +514 -0
- package/cli/src/commands/manage.ts +115 -0
- package/cli/src/index.ts +63 -0
- package/cli/tsconfig.json +14 -0
- package/docker-compose.yml +122 -0
- package/docs/agents/boss-agents.mdx +108 -0
- package/docs/agents/creating-agents.mdx +132 -0
- package/docs/agents/memory.mdx +113 -0
- package/docs/agents/tools.mdx +103 -0
- package/docs/configuration/env-vars.mdx +166 -0
- package/docs/configuration/mcp-servers.mdx +203 -0
- package/docs/configuration/slack-app.mdx +175 -0
- package/docs/docs.json +79 -0
- package/docs/favicon.svg +17 -0
- package/docs/features/history.mdx +60 -0
- package/docs/features/import-export.mdx +77 -0
- package/docs/features/logs.mdx +131 -0
- package/docs/features/multi-workspace.mdx +90 -0
- package/docs/features/scheduled-jobs.mdx +231 -0
- package/docs/features/users.mdx +92 -0
- package/docs/introduction.mdx +160 -0
- package/docs/logo/dark.svg +17 -0
- package/docs/logo/light.svg +17 -0
- package/docs/logo/wide-dark.svg +12 -0
- package/docs/logo/wide-light.svg +12 -0
- package/docs/quickstart.mdx +270 -0
- package/docs/self-hosting/docker.mdx +151 -0
- package/docs/self-hosting/production.mdx +176 -0
- package/package.json +20 -36
- package/packages/shared/dist/index.d.ts +8 -0
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +24 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/shared/dist/types.d.ts +584 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/types.js +39 -0
- package/packages/shared/dist/types.js.map +1 -0
- package/packages/shared/package.json +15 -0
- package/packages/shared/src/db/schema.sql +354 -0
- package/packages/shared/src/index.ts +8 -0
- package/packages/shared/src/types.ts +683 -0
- package/packages/shared/tsconfig.json +17 -0
- package/scripts/dev.sh +45 -0
- /package/{dist → cli/dist}/commands/init.d.ts +0 -0
- /package/{dist → cli/dist}/commands/init.js +0 -0
- /package/{dist → cli/dist}/commands/manage.d.ts +0 -0
- /package/{dist → cli/dist}/commands/manage.js +0 -0
- /package/{dist → cli/dist}/index.d.ts +0 -0
- /package/{dist → cli/dist}/index.js +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview REST API route for a single agent resource.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/agents/[id] — Get agent by ID
|
|
5
|
+
* PATCH /api/agents/[id] — Update agent config
|
|
6
|
+
* DELETE /api/agents/[id] — Remove agent
|
|
7
|
+
*
|
|
8
|
+
* @module web/api/agents/[id]
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
12
|
+
import { getAgentById, updateAgent, deleteAgent, publishAgentEvent } from '@/lib/db';
|
|
13
|
+
import type { UpdateAgentRequest } from '@slackhive/shared';
|
|
14
|
+
import { regenerateBossRegistry } from '@/lib/boss-registry';
|
|
15
|
+
import { guardAgentWrite, guardUserAdmin } from '@/lib/api-guard';
|
|
16
|
+
|
|
17
|
+
type RouteParams = { params: Promise<{ id: string }> };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* GET /api/agents/[id]
|
|
21
|
+
*
|
|
22
|
+
* @param {NextRequest} _req
|
|
23
|
+
* @param {RouteParams} ctx
|
|
24
|
+
* @returns {Promise<NextResponse>} Agent JSON or 404.
|
|
25
|
+
*/
|
|
26
|
+
export async function GET(_req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
27
|
+
try {
|
|
28
|
+
const { id } = await params;
|
|
29
|
+
const agent = await getAgentById(id);
|
|
30
|
+
if (!agent) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
31
|
+
return NextResponse.json(agent);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* PATCH /api/agents/[id]
|
|
39
|
+
* Updates mutable agent fields and triggers a reload event.
|
|
40
|
+
*
|
|
41
|
+
* @param {NextRequest} req - Partial UpdateAgentRequest body.
|
|
42
|
+
* @param {RouteParams} ctx
|
|
43
|
+
* @returns {Promise<NextResponse>} Updated agent JSON or error.
|
|
44
|
+
*/
|
|
45
|
+
export async function PATCH(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
46
|
+
try {
|
|
47
|
+
const { id } = await params;
|
|
48
|
+
const denied = await guardAgentWrite(req, id);
|
|
49
|
+
if (denied) return denied;
|
|
50
|
+
const body = (await req.json()) as Partial<UpdateAgentRequest>;
|
|
51
|
+
const updated = await updateAgent(id, body);
|
|
52
|
+
if (!updated) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
53
|
+
await publishAgentEvent({ type: 'reload', agentId: id });
|
|
54
|
+
await regenerateBossRegistry().catch(() => {});
|
|
55
|
+
return NextResponse.json(updated);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* DELETE /api/agents/[id]
|
|
63
|
+
* Removes an agent and publishes a stop event before deletion.
|
|
64
|
+
*
|
|
65
|
+
* @param {NextRequest} _req
|
|
66
|
+
* @param {RouteParams} ctx
|
|
67
|
+
* @returns {Promise<NextResponse>} 204 No Content or error.
|
|
68
|
+
*/
|
|
69
|
+
export async function DELETE(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
70
|
+
try {
|
|
71
|
+
const { id } = await params;
|
|
72
|
+
const denied = guardUserAdmin(req);
|
|
73
|
+
if (denied) return denied;
|
|
74
|
+
await publishAgentEvent({ type: 'stop', agentId: id });
|
|
75
|
+
await deleteAgent(id);
|
|
76
|
+
await regenerateBossRegistry().catch(() => {});
|
|
77
|
+
return new NextResponse(null, { status: 204 });
|
|
78
|
+
} catch (err) {
|
|
79
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DELETE /api/agents/[id]/skills/[skillId]
|
|
3
|
+
* Removes a skill file and triggers a reload event.
|
|
4
|
+
*
|
|
5
|
+
* @module web/api/agents/[id]/skills/[skillId]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { deleteSkill, publishAgentEvent, getAgentById, getAgentSkills, getAgentPermissions, getAgentMcpServers, createSnapshot } from '@/lib/db';
|
|
10
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
11
|
+
import { getSessionFromRequest } from '@/lib/auth';
|
|
12
|
+
import { skillToSnapshotSkill } from '@/lib/compile';
|
|
13
|
+
|
|
14
|
+
type RouteParams = { params: Promise<{ id: string; skillId: string }> };
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* DELETE /api/agents/[id]/skills/[skillId]
|
|
18
|
+
*
|
|
19
|
+
* @param {NextRequest} _req
|
|
20
|
+
* @param {RouteParams} ctx
|
|
21
|
+
* @returns {Promise<NextResponse>} 204 No Content or error.
|
|
22
|
+
*/
|
|
23
|
+
export async function DELETE(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
24
|
+
try {
|
|
25
|
+
const { id, skillId } = await params;
|
|
26
|
+
const denied = await guardAgentWrite(req, id);
|
|
27
|
+
if (denied) return denied;
|
|
28
|
+
|
|
29
|
+
// Snapshot before deletion
|
|
30
|
+
const session = getSessionFromRequest(req);
|
|
31
|
+
const [agent, currentSkills, perms, mcps] = await Promise.all([
|
|
32
|
+
getAgentById(id),
|
|
33
|
+
getAgentSkills(id),
|
|
34
|
+
getAgentPermissions(id),
|
|
35
|
+
getAgentMcpServers(id),
|
|
36
|
+
]);
|
|
37
|
+
await createSnapshot(
|
|
38
|
+
id, 'skills', session?.username ?? 'system', null,
|
|
39
|
+
currentSkills.map(skillToSnapshotSkill),
|
|
40
|
+
perms?.allowedTools ?? [],
|
|
41
|
+
perms?.deniedTools ?? [],
|
|
42
|
+
mcps.map(m => m.id),
|
|
43
|
+
agent?.claudeMd ?? '',
|
|
44
|
+
).catch(() => {});
|
|
45
|
+
|
|
46
|
+
await deleteSkill(skillId);
|
|
47
|
+
await publishAgentEvent({ type: 'reload', agentId: id });
|
|
48
|
+
return new NextResponse(null, { status: 204 });
|
|
49
|
+
} catch (err) {
|
|
50
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview REST API routes for agent skills.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/agents/[id]/skills — List all skills for an agent
|
|
5
|
+
* POST /api/agents/[id]/skills — Create or update a skill, then trigger reload
|
|
6
|
+
*
|
|
7
|
+
* @module web/api/agents/[id]/skills
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
11
|
+
import { getAgentById, getAgentSkills, upsertSkill, publishAgentEvent, getAgentPermissions, getAgentMcpServers, createSnapshot } from '@/lib/db';
|
|
12
|
+
import type { UpsertSkillRequest } from '@slackhive/shared';
|
|
13
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
14
|
+
import { getSessionFromRequest } from '@/lib/auth';
|
|
15
|
+
import { skillToSnapshotSkill } from '@/lib/compile';
|
|
16
|
+
|
|
17
|
+
type RouteParams = { params: Promise<{ id: string }> };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* GET /api/agents/[id]/skills
|
|
21
|
+
*
|
|
22
|
+
* @param {NextRequest} _req
|
|
23
|
+
* @param {RouteParams} ctx
|
|
24
|
+
* @returns {Promise<NextResponse>} JSON array of Skill objects.
|
|
25
|
+
*/
|
|
26
|
+
export async function GET(_req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
27
|
+
try {
|
|
28
|
+
const { id } = await params;
|
|
29
|
+
const skills = await getAgentSkills(id);
|
|
30
|
+
return NextResponse.json(skills);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* POST /api/agents/[id]/skills
|
|
38
|
+
* Creates or updates a skill file, then publishes a reload event.
|
|
39
|
+
*
|
|
40
|
+
* @param {NextRequest} req - Body: { category, filename, content, sortOrder? }
|
|
41
|
+
* @param {RouteParams} ctx
|
|
42
|
+
* @returns {Promise<NextResponse>} The upserted Skill or error.
|
|
43
|
+
*/
|
|
44
|
+
export async function POST(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
45
|
+
try {
|
|
46
|
+
const { id } = await params;
|
|
47
|
+
const denied = await guardAgentWrite(req, id);
|
|
48
|
+
if (denied) return denied;
|
|
49
|
+
const body = (await req.json()) as UpsertSkillRequest & { category: string; filename: string };
|
|
50
|
+
if (!body.category || !body.filename || body.content === undefined) {
|
|
51
|
+
return NextResponse.json({ error: 'category, filename, content are required' }, { status: 400 });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Snapshot current state before mutation (skip during bulk import)
|
|
55
|
+
const noSnapshot = req.nextUrl.searchParams.get('noSnapshot') === '1';
|
|
56
|
+
if (!noSnapshot) {
|
|
57
|
+
const session = getSessionFromRequest(req);
|
|
58
|
+
const [agent, currentSkills, perms, mcps] = await Promise.all([
|
|
59
|
+
getAgentById(id),
|
|
60
|
+
getAgentSkills(id),
|
|
61
|
+
getAgentPermissions(id),
|
|
62
|
+
getAgentMcpServers(id),
|
|
63
|
+
]);
|
|
64
|
+
await createSnapshot(
|
|
65
|
+
id, 'skills', session?.username ?? 'system', null,
|
|
66
|
+
currentSkills.map(skillToSnapshotSkill),
|
|
67
|
+
perms?.allowedTools ?? [],
|
|
68
|
+
perms?.deniedTools ?? [],
|
|
69
|
+
mcps.map(m => m.id),
|
|
70
|
+
agent?.claudeMd ?? '',
|
|
71
|
+
).catch(() => {});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const skill = await upsertSkill(id, body.category, body.filename, body.content, body.sortOrder ?? 0);
|
|
75
|
+
await publishAgentEvent({ type: 'reload', agentId: id });
|
|
76
|
+
return NextResponse.json(skill, { status: 201 });
|
|
77
|
+
} catch (err) {
|
|
78
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { getAgentById } from '@/lib/db';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GET /api/agents/[id]/slack-info
|
|
6
|
+
* Fetches live bot display name and @handle from Slack using the agent's bot token.
|
|
7
|
+
*/
|
|
8
|
+
export async function GET(
|
|
9
|
+
_req: NextRequest,
|
|
10
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
11
|
+
): Promise<NextResponse> {
|
|
12
|
+
try {
|
|
13
|
+
const { id } = await params;
|
|
14
|
+
const agent = await getAgentById(id);
|
|
15
|
+
if (!agent?.slackBotToken) return NextResponse.json({ error: 'No bot token' }, { status: 400 });
|
|
16
|
+
|
|
17
|
+
const authRes = await fetch('https://slack.com/api/auth.test', {
|
|
18
|
+
headers: { Authorization: `Bearer ${agent.slackBotToken}` },
|
|
19
|
+
});
|
|
20
|
+
const auth = await authRes.json();
|
|
21
|
+
if (!auth.ok) return NextResponse.json({ error: auth.error }, { status: 400 });
|
|
22
|
+
|
|
23
|
+
const userRes = await fetch(`https://slack.com/api/users.info?user=${auth.user_id}`, {
|
|
24
|
+
headers: { Authorization: `Bearer ${agent.slackBotToken}` },
|
|
25
|
+
});
|
|
26
|
+
const userData = await userRes.json();
|
|
27
|
+
const profile = userData?.user?.profile;
|
|
28
|
+
|
|
29
|
+
return NextResponse.json({
|
|
30
|
+
displayName: profile?.display_name || profile?.real_name || auth.user,
|
|
31
|
+
handle: auth.user,
|
|
32
|
+
botId: auth.bot_id,
|
|
33
|
+
teamName: auth.team,
|
|
34
|
+
});
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Restore an agent to a previous snapshot.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/agents/[id]/snapshots/[sid]/restore
|
|
5
|
+
*
|
|
6
|
+
* Replaces the agent's current skills, permissions, and MCP assignments
|
|
7
|
+
* with the state captured in the snapshot, then triggers a runner reload.
|
|
8
|
+
*
|
|
9
|
+
* @module web/api/agents/[id]/snapshots/[sid]/restore
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
13
|
+
import {
|
|
14
|
+
getSnapshotById,
|
|
15
|
+
deleteSkillsByAgent,
|
|
16
|
+
upsertSkill,
|
|
17
|
+
upsertPermissions,
|
|
18
|
+
setAgentMcps,
|
|
19
|
+
publishAgentEvent,
|
|
20
|
+
} from '@/lib/db';
|
|
21
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* POST /api/agents/[id]/snapshots/[sid]/restore
|
|
25
|
+
* Restores an agent to the state captured in a snapshot.
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<NextResponse>} 200 { ok: true } or error.
|
|
28
|
+
*/
|
|
29
|
+
export async function POST(
|
|
30
|
+
request: NextRequest,
|
|
31
|
+
{ params }: { params: Promise<{ id: string; sid: string }> }
|
|
32
|
+
): Promise<NextResponse> {
|
|
33
|
+
try {
|
|
34
|
+
const { id, sid } = await params;
|
|
35
|
+
const denied = await guardAgentWrite(request, id);
|
|
36
|
+
if (denied) return denied;
|
|
37
|
+
|
|
38
|
+
const snapshot = await getSnapshotById(sid);
|
|
39
|
+
if (!snapshot) return NextResponse.json({ error: 'Snapshot not found' }, { status: 404 });
|
|
40
|
+
if (snapshot.agentId !== id) return NextResponse.json({ error: 'Snapshot does not belong to this agent' }, { status: 400 });
|
|
41
|
+
|
|
42
|
+
// Replace skills
|
|
43
|
+
await deleteSkillsByAgent(id);
|
|
44
|
+
for (const s of snapshot.skillsJson) {
|
|
45
|
+
await upsertSkill(id, s.category, s.filename, s.content, s.sort_order);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Replace permissions
|
|
49
|
+
await upsertPermissions(id, snapshot.allowedTools, snapshot.deniedTools);
|
|
50
|
+
|
|
51
|
+
// Replace MCP assignments
|
|
52
|
+
await setAgentMcps(id, snapshot.mcpIds);
|
|
53
|
+
|
|
54
|
+
// Trigger runner reload
|
|
55
|
+
await publishAgentEvent({ type: 'reload', agentId: id });
|
|
56
|
+
|
|
57
|
+
return NextResponse.json({ ok: true });
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview REST API routes for a single agent snapshot.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/agents/[id]/snapshots/[sid] — Get full snapshot (including compiledMd)
|
|
5
|
+
* DELETE /api/agents/[id]/snapshots/[sid] — Delete snapshot
|
|
6
|
+
*
|
|
7
|
+
* @module web/api/agents/[id]/snapshots/[sid]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
11
|
+
import { getSnapshotById, deleteSnapshot } from '@/lib/db';
|
|
12
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* GET /api/agents/[id]/snapshots/[sid]
|
|
16
|
+
* Returns the full snapshot including compiledMd.
|
|
17
|
+
*
|
|
18
|
+
* @returns {Promise<NextResponse>} AgentSnapshot or 404.
|
|
19
|
+
*/
|
|
20
|
+
export async function GET(
|
|
21
|
+
_req: NextRequest,
|
|
22
|
+
{ params }: { params: Promise<{ id: string; sid: string }> }
|
|
23
|
+
): Promise<NextResponse> {
|
|
24
|
+
try {
|
|
25
|
+
const { sid } = await params;
|
|
26
|
+
const snapshot = await getSnapshotById(sid);
|
|
27
|
+
if (!snapshot) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
28
|
+
return NextResponse.json(snapshot);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* DELETE /api/agents/[id]/snapshots/[sid]
|
|
36
|
+
* Permanently deletes a snapshot.
|
|
37
|
+
*
|
|
38
|
+
* @returns {Promise<NextResponse>} 204 No Content.
|
|
39
|
+
*/
|
|
40
|
+
export async function DELETE(
|
|
41
|
+
request: NextRequest,
|
|
42
|
+
{ params }: { params: Promise<{ id: string; sid: string }> }
|
|
43
|
+
): Promise<NextResponse> {
|
|
44
|
+
try {
|
|
45
|
+
const { id, sid } = await params;
|
|
46
|
+
const denied = await guardAgentWrite(request, id);
|
|
47
|
+
if (denied) return denied;
|
|
48
|
+
await deleteSnapshot(sid);
|
|
49
|
+
return new NextResponse(null, { status: 204 });
|
|
50
|
+
} catch (err) {
|
|
51
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview REST API routes for agent snapshot collection.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/agents/[id]/snapshots — List all snapshots for an agent
|
|
5
|
+
* POST /api/agents/[id]/snapshots — Create a manual snapshot
|
|
6
|
+
*
|
|
7
|
+
* @module web/api/agents/[id]/snapshots
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
11
|
+
import {
|
|
12
|
+
getAgentById,
|
|
13
|
+
getAgentSkills,
|
|
14
|
+
getAgentPermissions,
|
|
15
|
+
getAgentMcpServers,
|
|
16
|
+
listSnapshots,
|
|
17
|
+
createSnapshot,
|
|
18
|
+
} from '@/lib/db';
|
|
19
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
20
|
+
import { getSessionFromRequest } from '@/lib/auth';
|
|
21
|
+
import { skillToSnapshotSkill } from '@/lib/compile';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* GET /api/agents/[id]/snapshots
|
|
25
|
+
* Returns all snapshots for an agent, newest first.
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<NextResponse>} JSON array of AgentSnapshot objects.
|
|
28
|
+
*/
|
|
29
|
+
export async function GET(
|
|
30
|
+
_req: NextRequest,
|
|
31
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
32
|
+
): Promise<NextResponse> {
|
|
33
|
+
try {
|
|
34
|
+
const { id } = await params;
|
|
35
|
+
const snapshots = await listSnapshots(id);
|
|
36
|
+
// Omit compiledMd from list view to keep payload small
|
|
37
|
+
return NextResponse.json(snapshots.map(s => ({ ...s, compiledMd: undefined })));
|
|
38
|
+
} catch (err) {
|
|
39
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* POST /api/agents/[id]/snapshots
|
|
45
|
+
* Creates a manual snapshot of the agent's current configuration.
|
|
46
|
+
*
|
|
47
|
+
* @param {NextRequest} request - Body: { label?: string }
|
|
48
|
+
* @returns {Promise<NextResponse>} The created AgentSnapshot (201).
|
|
49
|
+
*/
|
|
50
|
+
export async function POST(
|
|
51
|
+
request: NextRequest,
|
|
52
|
+
{ params }: { params: Promise<{ id: string }> }
|
|
53
|
+
): Promise<NextResponse> {
|
|
54
|
+
try {
|
|
55
|
+
const { id } = await params;
|
|
56
|
+
const denied = await guardAgentWrite(request, id);
|
|
57
|
+
if (denied) return denied;
|
|
58
|
+
const agent = await getAgentById(id);
|
|
59
|
+
if (!agent) return NextResponse.json({ error: 'Agent not found' }, { status: 404 });
|
|
60
|
+
|
|
61
|
+
const body = await request.json().catch(() => ({}));
|
|
62
|
+
const label: string | null = body.label ?? null;
|
|
63
|
+
|
|
64
|
+
const session = getSessionFromRequest(request);
|
|
65
|
+
const [skills, perms, mcps] = await Promise.all([
|
|
66
|
+
getAgentSkills(id),
|
|
67
|
+
getAgentPermissions(id),
|
|
68
|
+
getAgentMcpServers(id),
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
const snapshot = await createSnapshot(
|
|
72
|
+
id, 'manual', session?.username ?? 'system', label,
|
|
73
|
+
skills.map(skillToSnapshotSkill),
|
|
74
|
+
perms?.allowedTools ?? [],
|
|
75
|
+
perms?.deniedTools ?? [],
|
|
76
|
+
mcps.map(m => m.id),
|
|
77
|
+
agent?.claudeMd ?? '',
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return NextResponse.json(snapshot, { status: 201 });
|
|
81
|
+
} catch (err) {
|
|
82
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview POST /api/agents/[id]/start
|
|
3
|
+
* Publishes a start event so the runner spins up the agent's Bolt app.
|
|
4
|
+
*
|
|
5
|
+
* @module web/api/agents/[id]/start
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { getAgentById, updateAgentStatus, updateAgentEnabled, publishAgentEvent } from '@/lib/db';
|
|
10
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
11
|
+
|
|
12
|
+
type RouteParams = { params: Promise<{ id: string }> };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* POST /api/agents/[id]/start
|
|
16
|
+
*
|
|
17
|
+
* @param {NextRequest} _req
|
|
18
|
+
* @param {RouteParams} ctx
|
|
19
|
+
* @returns {Promise<NextResponse>} 200 on success, 404 or 500 on error.
|
|
20
|
+
*/
|
|
21
|
+
export async function POST(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
22
|
+
try {
|
|
23
|
+
const { id } = await params;
|
|
24
|
+
const denied = await guardAgentWrite(req, id);
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
const agent = await getAgentById(id);
|
|
27
|
+
if (!agent) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
28
|
+
await publishAgentEvent({ type: 'start', agentId: id });
|
|
29
|
+
await updateAgentStatus(id, 'running');
|
|
30
|
+
await updateAgentEnabled(id, true);
|
|
31
|
+
return NextResponse.json({ ok: true });
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview POST /api/agents/[id]/stop
|
|
3
|
+
* Publishes a stop event so the runner tears down the agent's Bolt app.
|
|
4
|
+
*
|
|
5
|
+
* @module web/api/agents/[id]/stop
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
9
|
+
import { getAgentById, updateAgentStatus, updateAgentEnabled, publishAgentEvent } from '@/lib/db';
|
|
10
|
+
import { guardAgentWrite } from '@/lib/api-guard';
|
|
11
|
+
|
|
12
|
+
type RouteParams = { params: Promise<{ id: string }> };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* POST /api/agents/[id]/stop
|
|
16
|
+
*
|
|
17
|
+
* @param {NextRequest} _req
|
|
18
|
+
* @param {RouteParams} ctx
|
|
19
|
+
* @returns {Promise<NextResponse>} 200 on success, 404 or 500 on error.
|
|
20
|
+
*/
|
|
21
|
+
export async function POST(req: NextRequest, { params }: RouteParams): Promise<NextResponse> {
|
|
22
|
+
try {
|
|
23
|
+
const { id } = await params;
|
|
24
|
+
const denied = await guardAgentWrite(req, id);
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
const agent = await getAgentById(id);
|
|
27
|
+
if (!agent) return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
|
28
|
+
await publishAgentEvent({ type: 'stop', agentId: id });
|
|
29
|
+
await updateAgentStatus(id, 'stopped');
|
|
30
|
+
await updateAgentEnabled(id, false);
|
|
31
|
+
return NextResponse.json({ ok: true });
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview REST API route for agent collection operations.
|
|
3
|
+
*
|
|
4
|
+
* GET /api/agents — List all agents
|
|
5
|
+
* POST /api/agents — Create a new agent
|
|
6
|
+
*
|
|
7
|
+
* @module web/api/agents
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
11
|
+
import {
|
|
12
|
+
getAllAgents,
|
|
13
|
+
createAgent,
|
|
14
|
+
setAgentMcps,
|
|
15
|
+
upsertSkill,
|
|
16
|
+
upsertPermissions,
|
|
17
|
+
publishAgentEvent,
|
|
18
|
+
} from '@/lib/db';
|
|
19
|
+
import type { CreateAgentRequest } from '@slackhive/shared';
|
|
20
|
+
import { SKILL_TEMPLATES } from '@/lib/skill-templates';
|
|
21
|
+
import { regenerateBossRegistry } from '@/lib/boss-registry';
|
|
22
|
+
import { guardAdmin } from '@/lib/api-guard';
|
|
23
|
+
import { getSessionFromRequest } from '@/lib/auth';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* GET /api/agents
|
|
27
|
+
* Returns all registered agents ordered boss-first.
|
|
28
|
+
*
|
|
29
|
+
* @returns {Promise<NextResponse>} JSON array of Agent objects.
|
|
30
|
+
*/
|
|
31
|
+
export async function GET(): Promise<NextResponse> {
|
|
32
|
+
try {
|
|
33
|
+
const agents = await getAllAgents();
|
|
34
|
+
return NextResponse.json(agents);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
return NextResponse.json({ error: (err as Error).message }, { status: 500 });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* POST /api/agents
|
|
42
|
+
* Creates a new agent with its initial configuration.
|
|
43
|
+
* Also bootstraps skills from a template and assigns MCPs.
|
|
44
|
+
* Publishes a start event so the runner picks it up immediately.
|
|
45
|
+
*
|
|
46
|
+
* @param {NextRequest} request - Request body matching CreateAgentRequest.
|
|
47
|
+
* @returns {Promise<NextResponse>} The created Agent (201), or error.
|
|
48
|
+
*/
|
|
49
|
+
export async function POST(request: NextRequest): Promise<NextResponse> {
|
|
50
|
+
const denied = guardAdmin(request);
|
|
51
|
+
if (denied) return denied;
|
|
52
|
+
try {
|
|
53
|
+
const body = (await request.json()) as CreateAgentRequest;
|
|
54
|
+
|
|
55
|
+
// Validate required fields
|
|
56
|
+
if (!body.slug || !body.name || !body.slackBotToken || !body.slackAppToken || !body.slackSigningSecret) {
|
|
57
|
+
return NextResponse.json(
|
|
58
|
+
{ error: 'slug, name, slackBotToken, slackAppToken, slackSigningSecret are required' },
|
|
59
|
+
{ status: 400 }
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Create the agent record, tracking who created it
|
|
64
|
+
const session = getSessionFromRequest(request);
|
|
65
|
+
const agent = await createAgent(body, session?.username ?? 'system');
|
|
66
|
+
|
|
67
|
+
// Assign MCPs if provided
|
|
68
|
+
if (body.mcpServerIds?.length) {
|
|
69
|
+
await setAgentMcps(agent.id, body.mcpServerIds);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Boss agents skip skill template — their CLAUDE.md is auto-generated by boss-registry
|
|
73
|
+
if (!agent.isBoss) {
|
|
74
|
+
const template = body.skillTemplate ?? 'blank';
|
|
75
|
+
const skills = SKILL_TEMPLATES[template](agent);
|
|
76
|
+
for (const skill of skills) {
|
|
77
|
+
await upsertSkill(agent.id, skill.category, skill.filename, skill.content, skill.sortOrder);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Create default permissions (Read + selected MCP tools)
|
|
82
|
+
const allowedTools = ['Read'];
|
|
83
|
+
await upsertPermissions(agent.id, allowedTools, []);
|
|
84
|
+
|
|
85
|
+
// Signal the runner to start this agent
|
|
86
|
+
await publishAgentEvent({ type: 'start', agentId: agent.id });
|
|
87
|
+
|
|
88
|
+
// Regenerate boss registry now that team has a new member
|
|
89
|
+
await regenerateBossRegistry().catch(() => {});
|
|
90
|
+
|
|
91
|
+
return NextResponse.json(agent, { status: 201 });
|
|
92
|
+
} catch (err) {
|
|
93
|
+
const message = (err as Error).message;
|
|
94
|
+
if (message.includes('unique')) {
|
|
95
|
+
return NextResponse.json({ error: 'An agent with this slug already exists' }, { status: 409 });
|
|
96
|
+
}
|
|
97
|
+
return NextResponse.json({ error: message }, { status: 500 });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Login API — authenticates user and sets session cookie.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/auth/login — accepts `{ username, password }`.
|
|
5
|
+
*
|
|
6
|
+
* @module web/api/auth/login
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { NextResponse } from 'next/server';
|
|
10
|
+
import { authenticateUser, signSession, COOKIE_NAME } from '@/lib/auth';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Authenticates a user and sets an HMAC-signed session cookie.
|
|
14
|
+
*
|
|
15
|
+
* @param {Request} req - JSON body with `username` and `password`.
|
|
16
|
+
* @returns {Promise<NextResponse>} JSON response with role or 401.
|
|
17
|
+
*/
|
|
18
|
+
export async function POST(req: Request): Promise<NextResponse> {
|
|
19
|
+
const { username, password } = await req.json();
|
|
20
|
+
|
|
21
|
+
if (!username || !password) {
|
|
22
|
+
return NextResponse.json({ error: 'Username and password required' }, { status: 400 });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const session = await authenticateUser(username, password);
|
|
26
|
+
if (!session) {
|
|
27
|
+
return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const cookie = signSession(session);
|
|
31
|
+
const res = NextResponse.json({ ok: true, username: session.username, role: session.role });
|
|
32
|
+
res.cookies.set(COOKIE_NAME, cookie, {
|
|
33
|
+
httpOnly: true,
|
|
34
|
+
sameSite: 'lax',
|
|
35
|
+
path: '/',
|
|
36
|
+
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
37
|
+
});
|
|
38
|
+
return res;
|
|
39
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Logout API — clears the session cookie.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/auth/logout
|
|
5
|
+
*
|
|
6
|
+
* @module web/api/auth/logout
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { NextResponse } from 'next/server';
|
|
10
|
+
import { COOKIE_NAME } from '@/lib/auth';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Clears the auth session cookie.
|
|
14
|
+
*
|
|
15
|
+
* @returns {Promise<NextResponse>} JSON confirmation.
|
|
16
|
+
*/
|
|
17
|
+
export async function POST(): Promise<NextResponse> {
|
|
18
|
+
const res = NextResponse.json({ ok: true });
|
|
19
|
+
res.cookies.set(COOKIE_NAME, '', { httpOnly: true, path: '/', maxAge: 0 });
|
|
20
|
+
return res;
|
|
21
|
+
}
|