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.
Files changed (542) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.example +44 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +65 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +38 -0
  6. package/.github/PULL_REQUEST_TEMPLATE.md +27 -0
  7. package/.github/dependabot.yml +20 -0
  8. package/.github/workflows/audit.yml +149 -0
  9. package/.github/workflows/ci.yml +135 -0
  10. package/CHANGELOG.md +52 -0
  11. package/CODE_OF_CONDUCT.md +37 -0
  12. package/CONTRIBUTING.md +204 -0
  13. package/LICENSE +21 -0
  14. package/README.md +19 -0
  15. package/SECURITY.md +47 -0
  16. package/apps/runner/Dockerfile +33 -0
  17. package/apps/runner/dist/__tests__/channel-restrictions.test.d.ts +8 -0
  18. package/apps/runner/dist/__tests__/channel-restrictions.test.js +63 -0
  19. package/apps/runner/dist/__tests__/channel-restrictions.test.js.map +1 -0
  20. package/apps/runner/dist/__tests__/claude-handler-resolve.test.d.ts +20 -0
  21. package/apps/runner/dist/__tests__/claude-handler-resolve.test.js +178 -0
  22. package/apps/runner/dist/__tests__/claude-handler-resolve.test.js.map +1 -0
  23. package/apps/runner/dist/__tests__/compile-claude-md.test.d.ts +13 -0
  24. package/apps/runner/dist/__tests__/compile-claude-md.test.js +144 -0
  25. package/apps/runner/dist/__tests__/compile-claude-md.test.js.map +1 -0
  26. package/apps/runner/dist/__tests__/memory-sync.test.d.ts +11 -0
  27. package/apps/runner/dist/__tests__/memory-sync.test.js +56 -0
  28. package/apps/runner/dist/__tests__/memory-sync.test.js.map +1 -0
  29. package/apps/runner/dist/__tests__/slack-file-support.test.d.ts +9 -0
  30. package/apps/runner/dist/__tests__/slack-file-support.test.js +271 -0
  31. package/apps/runner/dist/__tests__/slack-file-support.test.js.map +1 -0
  32. package/apps/runner/dist/__tests__/slack-formatting.test.d.ts +12 -0
  33. package/apps/runner/dist/__tests__/slack-formatting.test.js +400 -0
  34. package/apps/runner/dist/__tests__/slack-formatting.test.js.map +1 -0
  35. package/apps/runner/dist/__tests__/thread-context.test.d.ts +12 -0
  36. package/apps/runner/dist/__tests__/thread-context.test.js +182 -0
  37. package/apps/runner/dist/__tests__/thread-context.test.js.map +1 -0
  38. package/apps/runner/dist/agent-runner.d.ts +118 -0
  39. package/apps/runner/dist/agent-runner.js +352 -0
  40. package/apps/runner/dist/agent-runner.js.map +1 -0
  41. package/apps/runner/dist/claude-handler.d.ts +122 -0
  42. package/apps/runner/dist/claude-handler.js +402 -0
  43. package/apps/runner/dist/claude-handler.js.map +1 -0
  44. package/apps/runner/dist/compile-claude-md.d.ts +59 -0
  45. package/apps/runner/dist/compile-claude-md.js +291 -0
  46. package/apps/runner/dist/compile-claude-md.js.map +1 -0
  47. package/apps/runner/dist/correction-handler.d.ts +46 -0
  48. package/apps/runner/dist/correction-handler.js +162 -0
  49. package/apps/runner/dist/correction-handler.js.map +1 -0
  50. package/apps/runner/dist/correction-manager.d.ts +53 -0
  51. package/apps/runner/dist/correction-manager.js +241 -0
  52. package/apps/runner/dist/correction-manager.js.map +1 -0
  53. package/apps/runner/dist/db.d.ts +193 -0
  54. package/apps/runner/dist/db.js +492 -0
  55. package/apps/runner/dist/db.js.map +1 -0
  56. package/apps/runner/dist/index.d.ts +9 -0
  57. package/apps/runner/dist/index.js +43 -0
  58. package/apps/runner/dist/index.js.map +1 -0
  59. package/apps/runner/dist/job-scheduler.d.ts +57 -0
  60. package/apps/runner/dist/job-scheduler.js +150 -0
  61. package/apps/runner/dist/job-scheduler.js.map +1 -0
  62. package/apps/runner/dist/logger.d.ts +32 -0
  63. package/apps/runner/dist/logger.js +52 -0
  64. package/apps/runner/dist/logger.js.map +1 -0
  65. package/apps/runner/dist/mcp-process-manager.d.ts +38 -0
  66. package/apps/runner/dist/mcp-process-manager.js +189 -0
  67. package/apps/runner/dist/mcp-process-manager.js.map +1 -0
  68. package/apps/runner/dist/memory-mcp.d.ts +14 -0
  69. package/apps/runner/dist/memory-mcp.js +88 -0
  70. package/apps/runner/dist/memory-mcp.js.map +1 -0
  71. package/apps/runner/dist/memory-watcher.d.ts +78 -0
  72. package/apps/runner/dist/memory-watcher.js +220 -0
  73. package/apps/runner/dist/memory-watcher.js.map +1 -0
  74. package/apps/runner/dist/slack-handler.d.ts +120 -0
  75. package/apps/runner/dist/slack-handler.js +843 -0
  76. package/apps/runner/dist/slack-handler.js.map +1 -0
  77. package/apps/runner/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  78. package/apps/runner/package.json +42 -0
  79. package/apps/runner/src/__tests__/channel-restrictions.test.ts +75 -0
  80. package/apps/runner/src/__tests__/claude-handler-resolve.test.ts +160 -0
  81. package/apps/runner/src/__tests__/compile-claude-md.test.ts +139 -0
  82. package/apps/runner/src/__tests__/memory-sync.test.ts +59 -0
  83. package/apps/runner/src/__tests__/slack-file-support.test.ts +376 -0
  84. package/apps/runner/src/__tests__/slack-formatting.test.ts +495 -0
  85. package/apps/runner/src/__tests__/thread-context.test.ts +215 -0
  86. package/apps/runner/src/agent-runner.ts +397 -0
  87. package/apps/runner/src/claude-handler.ts +475 -0
  88. package/apps/runner/src/compile-claude-md.ts +283 -0
  89. package/apps/runner/src/correction-handler.ts +191 -0
  90. package/apps/runner/src/correction-manager.ts +285 -0
  91. package/apps/runner/src/db.ts +604 -0
  92. package/apps/runner/src/index.ts +46 -0
  93. package/apps/runner/src/job-scheduler.ts +165 -0
  94. package/apps/runner/src/logger.ts +49 -0
  95. package/apps/runner/src/mcp-process-manager.ts +195 -0
  96. package/apps/runner/src/memory-mcp.ts +85 -0
  97. package/apps/runner/src/memory-watcher.ts +215 -0
  98. package/apps/runner/src/slack-handler.ts +929 -0
  99. package/apps/runner/tsconfig.json +17 -0
  100. package/apps/runner/vitest.config.mts +17 -0
  101. package/apps/web/.eslintrc.json +3 -0
  102. package/apps/web/.next/app-build-manifest.json +323 -0
  103. package/apps/web/.next/app-path-routes-manifest.json +46 -0
  104. package/apps/web/.next/build-manifest.json +33 -0
  105. package/apps/web/.next/cache/.previewinfo +1 -0
  106. package/apps/web/.next/cache/.rscinfo +1 -0
  107. package/apps/web/.next/cache/webpack/client-production/0.pack +0 -0
  108. package/apps/web/.next/cache/webpack/client-production/1.pack +0 -0
  109. package/apps/web/.next/cache/webpack/client-production/2.pack +0 -0
  110. package/apps/web/.next/cache/webpack/client-production/3.pack +0 -0
  111. package/apps/web/.next/cache/webpack/client-production/4.pack +0 -0
  112. package/apps/web/.next/cache/webpack/client-production/index.pack +0 -0
  113. package/apps/web/.next/cache/webpack/client-production/index.pack.old +0 -0
  114. package/apps/web/.next/cache/webpack/edge-server-production/0.pack +0 -0
  115. package/apps/web/.next/cache/webpack/edge-server-production/1.pack +0 -0
  116. package/apps/web/.next/cache/webpack/edge-server-production/index.pack +0 -0
  117. package/apps/web/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  118. package/apps/web/.next/cache/webpack/server-production/0.pack +0 -0
  119. package/apps/web/.next/cache/webpack/server-production/1.pack +0 -0
  120. package/apps/web/.next/cache/webpack/server-production/2.pack +0 -0
  121. package/apps/web/.next/cache/webpack/server-production/index.pack +0 -0
  122. package/apps/web/.next/cache/webpack/server-production/index.pack.old +0 -0
  123. package/apps/web/.next/diagnostics/build-diagnostics.json +6 -0
  124. package/apps/web/.next/diagnostics/framework.json +1 -0
  125. package/apps/web/.next/package.json +1 -0
  126. package/apps/web/.next/react-loadable-manifest.json +1 -0
  127. package/apps/web/.next/server/app/_not-found/page.js +2 -0
  128. package/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -0
  129. package/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  130. package/apps/web/.next/server/app/agents/[slug]/page.js +4 -0
  131. package/apps/web/.next/server/app/agents/[slug]/page.js.nft.json +1 -0
  132. package/apps/web/.next/server/app/agents/[slug]/page_client-reference-manifest.js +1 -0
  133. package/apps/web/.next/server/app/agents/new/page.js +2 -0
  134. package/apps/web/.next/server/app/agents/new/page.js.nft.json +1 -0
  135. package/apps/web/.next/server/app/agents/new/page_client-reference-manifest.js +1 -0
  136. package/apps/web/.next/server/app/api/agents/[id]/access/route.js +1 -0
  137. package/apps/web/.next/server/app/api/agents/[id]/access/route.js.nft.json +1 -0
  138. package/apps/web/.next/server/app/api/agents/[id]/access/route_client-reference-manifest.js +1 -0
  139. package/apps/web/.next/server/app/api/agents/[id]/claude-md/route.js +6 -0
  140. package/apps/web/.next/server/app/api/agents/[id]/claude-md/route.js.nft.json +1 -0
  141. package/apps/web/.next/server/app/api/agents/[id]/claude-md/route_client-reference-manifest.js +1 -0
  142. package/apps/web/.next/server/app/api/agents/[id]/logs/route.js +3 -0
  143. package/apps/web/.next/server/app/api/agents/[id]/logs/route.js.nft.json +1 -0
  144. package/apps/web/.next/server/app/api/agents/[id]/logs/route_client-reference-manifest.js +1 -0
  145. package/apps/web/.next/server/app/api/agents/[id]/manifest/route.js +1 -0
  146. package/apps/web/.next/server/app/api/agents/[id]/manifest/route.js.nft.json +1 -0
  147. package/apps/web/.next/server/app/api/agents/[id]/manifest/route_client-reference-manifest.js +1 -0
  148. package/apps/web/.next/server/app/api/agents/[id]/mcps/route.js +1 -0
  149. package/apps/web/.next/server/app/api/agents/[id]/mcps/route.js.nft.json +1 -0
  150. package/apps/web/.next/server/app/api/agents/[id]/mcps/route_client-reference-manifest.js +1 -0
  151. package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route.js +1 -0
  152. package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route.js.nft.json +1 -0
  153. package/apps/web/.next/server/app/api/agents/[id]/memories/[memId]/route_client-reference-manifest.js +1 -0
  154. package/apps/web/.next/server/app/api/agents/[id]/memories/route.js +1 -0
  155. package/apps/web/.next/server/app/api/agents/[id]/memories/route.js.nft.json +1 -0
  156. package/apps/web/.next/server/app/api/agents/[id]/memories/route_client-reference-manifest.js +1 -0
  157. package/apps/web/.next/server/app/api/agents/[id]/permissions/route.js +1 -0
  158. package/apps/web/.next/server/app/api/agents/[id]/permissions/route.js.nft.json +1 -0
  159. package/apps/web/.next/server/app/api/agents/[id]/permissions/route_client-reference-manifest.js +1 -0
  160. package/apps/web/.next/server/app/api/agents/[id]/reload/route.js +1 -0
  161. package/apps/web/.next/server/app/api/agents/[id]/reload/route.js.nft.json +1 -0
  162. package/apps/web/.next/server/app/api/agents/[id]/reload/route_client-reference-manifest.js +1 -0
  163. package/apps/web/.next/server/app/api/agents/[id]/restrictions/route.js +1 -0
  164. package/apps/web/.next/server/app/api/agents/[id]/restrictions/route.js.nft.json +1 -0
  165. package/apps/web/.next/server/app/api/agents/[id]/restrictions/route_client-reference-manifest.js +1 -0
  166. package/apps/web/.next/server/app/api/agents/[id]/route.js +33 -0
  167. package/apps/web/.next/server/app/api/agents/[id]/route.js.nft.json +1 -0
  168. package/apps/web/.next/server/app/api/agents/[id]/route_client-reference-manifest.js +1 -0
  169. package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route.js +1 -0
  170. package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route.js.nft.json +1 -0
  171. package/apps/web/.next/server/app/api/agents/[id]/skills/[skillId]/route_client-reference-manifest.js +1 -0
  172. package/apps/web/.next/server/app/api/agents/[id]/skills/route.js +1 -0
  173. package/apps/web/.next/server/app/api/agents/[id]/skills/route.js.nft.json +1 -0
  174. package/apps/web/.next/server/app/api/agents/[id]/skills/route_client-reference-manifest.js +1 -0
  175. package/apps/web/.next/server/app/api/agents/[id]/slack-info/route.js +1 -0
  176. package/apps/web/.next/server/app/api/agents/[id]/slack-info/route.js.nft.json +1 -0
  177. package/apps/web/.next/server/app/api/agents/[id]/slack-info/route_client-reference-manifest.js +1 -0
  178. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route.js +1 -0
  179. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route.js.nft.json +1 -0
  180. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/restore/route_client-reference-manifest.js +1 -0
  181. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route.js +1 -0
  182. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route.js.nft.json +1 -0
  183. package/apps/web/.next/server/app/api/agents/[id]/snapshots/[sid]/route_client-reference-manifest.js +1 -0
  184. package/apps/web/.next/server/app/api/agents/[id]/snapshots/route.js +1 -0
  185. package/apps/web/.next/server/app/api/agents/[id]/snapshots/route.js.nft.json +1 -0
  186. package/apps/web/.next/server/app/api/agents/[id]/snapshots/route_client-reference-manifest.js +1 -0
  187. package/apps/web/.next/server/app/api/agents/[id]/start/route.js +1 -0
  188. package/apps/web/.next/server/app/api/agents/[id]/start/route.js.nft.json +1 -0
  189. package/apps/web/.next/server/app/api/agents/[id]/start/route_client-reference-manifest.js +1 -0
  190. package/apps/web/.next/server/app/api/agents/[id]/stop/route.js +1 -0
  191. package/apps/web/.next/server/app/api/agents/[id]/stop/route.js.nft.json +1 -0
  192. package/apps/web/.next/server/app/api/agents/[id]/stop/route_client-reference-manifest.js +1 -0
  193. package/apps/web/.next/server/app/api/agents/route.js +91 -0
  194. package/apps/web/.next/server/app/api/agents/route.js.nft.json +1 -0
  195. package/apps/web/.next/server/app/api/agents/route_client-reference-manifest.js +1 -0
  196. package/apps/web/.next/server/app/api/auth/login/route.js +1 -0
  197. package/apps/web/.next/server/app/api/auth/login/route.js.nft.json +1 -0
  198. package/apps/web/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -0
  199. package/apps/web/.next/server/app/api/auth/logout/route.js +1 -0
  200. package/apps/web/.next/server/app/api/auth/logout/route.js.nft.json +1 -0
  201. package/apps/web/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -0
  202. package/apps/web/.next/server/app/api/auth/me/route.js +1 -0
  203. package/apps/web/.next/server/app/api/auth/me/route.js.nft.json +1 -0
  204. package/apps/web/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -0
  205. package/apps/web/.next/server/app/api/auth/users/[id]/route.js +1 -0
  206. package/apps/web/.next/server/app/api/auth/users/[id]/route.js.nft.json +1 -0
  207. package/apps/web/.next/server/app/api/auth/users/[id]/route_client-reference-manifest.js +1 -0
  208. package/apps/web/.next/server/app/api/auth/users/route.js +1 -0
  209. package/apps/web/.next/server/app/api/auth/users/route.js.nft.json +1 -0
  210. package/apps/web/.next/server/app/api/auth/users/route_client-reference-manifest.js +1 -0
  211. package/apps/web/.next/server/app/api/env-vars/[key]/route.js +1 -0
  212. package/apps/web/.next/server/app/api/env-vars/[key]/route.js.nft.json +1 -0
  213. package/apps/web/.next/server/app/api/env-vars/[key]/route_client-reference-manifest.js +1 -0
  214. package/apps/web/.next/server/app/api/env-vars/route.js +1 -0
  215. package/apps/web/.next/server/app/api/env-vars/route.js.nft.json +1 -0
  216. package/apps/web/.next/server/app/api/env-vars/route_client-reference-manifest.js +1 -0
  217. package/apps/web/.next/server/app/api/jobs/[id]/route.js +1 -0
  218. package/apps/web/.next/server/app/api/jobs/[id]/route.js.nft.json +1 -0
  219. package/apps/web/.next/server/app/api/jobs/[id]/route_client-reference-manifest.js +1 -0
  220. package/apps/web/.next/server/app/api/jobs/[id]/runs/route.js +1 -0
  221. package/apps/web/.next/server/app/api/jobs/[id]/runs/route.js.nft.json +1 -0
  222. package/apps/web/.next/server/app/api/jobs/[id]/runs/route_client-reference-manifest.js +1 -0
  223. package/apps/web/.next/server/app/api/jobs/route.js +1 -0
  224. package/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -0
  225. package/apps/web/.next/server/app/api/jobs/route_client-reference-manifest.js +1 -0
  226. package/apps/web/.next/server/app/api/mcps/[id]/route.js +1 -0
  227. package/apps/web/.next/server/app/api/mcps/[id]/route.js.nft.json +1 -0
  228. package/apps/web/.next/server/app/api/mcps/[id]/route_client-reference-manifest.js +1 -0
  229. package/apps/web/.next/server/app/api/mcps/[id]/test/route.js +1 -0
  230. package/apps/web/.next/server/app/api/mcps/[id]/test/route.js.nft.json +1 -0
  231. package/apps/web/.next/server/app/api/mcps/[id]/test/route_client-reference-manifest.js +1 -0
  232. package/apps/web/.next/server/app/api/mcps/route.js +1 -0
  233. package/apps/web/.next/server/app/api/mcps/route.js.nft.json +1 -0
  234. package/apps/web/.next/server/app/api/mcps/route_client-reference-manifest.js +1 -0
  235. package/apps/web/.next/server/app/api/settings/route.js +1 -0
  236. package/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -0
  237. package/apps/web/.next/server/app/api/settings/route_client-reference-manifest.js +1 -0
  238. package/apps/web/.next/server/app/icon.svg/route.js +1 -0
  239. package/apps/web/.next/server/app/icon.svg/route.js.nft.json +1 -0
  240. package/apps/web/.next/server/app/jobs/page.js +2 -0
  241. package/apps/web/.next/server/app/jobs/page.js.nft.json +1 -0
  242. package/apps/web/.next/server/app/jobs/page_client-reference-manifest.js +1 -0
  243. package/apps/web/.next/server/app/login/page.js +2 -0
  244. package/apps/web/.next/server/app/login/page.js.nft.json +1 -0
  245. package/apps/web/.next/server/app/login/page_client-reference-manifest.js +1 -0
  246. package/apps/web/.next/server/app/page.js +2 -0
  247. package/apps/web/.next/server/app/page.js.nft.json +1 -0
  248. package/apps/web/.next/server/app/page_client-reference-manifest.js +1 -0
  249. package/apps/web/.next/server/app/settings/env-vars/page.js +2 -0
  250. package/apps/web/.next/server/app/settings/env-vars/page.js.nft.json +1 -0
  251. package/apps/web/.next/server/app/settings/env-vars/page_client-reference-manifest.js +1 -0
  252. package/apps/web/.next/server/app/settings/mcps/page.js +2 -0
  253. package/apps/web/.next/server/app/settings/mcps/page.js.nft.json +1 -0
  254. package/apps/web/.next/server/app/settings/mcps/page_client-reference-manifest.js +1 -0
  255. package/apps/web/.next/server/app/settings/page.js +2 -0
  256. package/apps/web/.next/server/app/settings/page.js.nft.json +1 -0
  257. package/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -0
  258. package/apps/web/.next/server/app-paths-manifest.json +46 -0
  259. package/apps/web/.next/server/chunks/1157.js +9 -0
  260. package/apps/web/.next/server/chunks/2287.js +1 -0
  261. package/apps/web/.next/server/chunks/3444.js +1 -0
  262. package/apps/web/.next/server/chunks/383.js +6 -0
  263. package/apps/web/.next/server/chunks/4012.js +58 -0
  264. package/apps/web/.next/server/chunks/6791.js +1 -0
  265. package/apps/web/.next/server/chunks/7171.js +1 -0
  266. package/apps/web/.next/server/chunks/8819.js +22 -0
  267. package/apps/web/.next/server/edge-runtime-webpack.js +2 -0
  268. package/apps/web/.next/server/edge-runtime-webpack.js.map +1 -0
  269. package/apps/web/.next/server/interception-route-rewrite-manifest.js +1 -0
  270. package/apps/web/.next/server/middleware-build-manifest.js +1 -0
  271. package/apps/web/.next/server/middleware-manifest.json +32 -0
  272. package/apps/web/.next/server/middleware-react-loadable-manifest.js +1 -0
  273. package/apps/web/.next/server/next-font-manifest.js +1 -0
  274. package/apps/web/.next/server/next-font-manifest.json +1 -0
  275. package/apps/web/.next/server/pages/_app.js +1 -0
  276. package/apps/web/.next/server/pages/_app.js.nft.json +1 -0
  277. package/apps/web/.next/server/pages/_document.js +1 -0
  278. package/apps/web/.next/server/pages/_document.js.nft.json +1 -0
  279. package/apps/web/.next/server/pages/_error.js +19 -0
  280. package/apps/web/.next/server/pages/_error.js.nft.json +1 -0
  281. package/apps/web/.next/server/pages-manifest.json +5 -0
  282. package/apps/web/.next/server/server-reference-manifest.js +1 -0
  283. package/apps/web/.next/server/server-reference-manifest.json +1 -0
  284. package/apps/web/.next/server/src/middleware.js +14 -0
  285. package/apps/web/.next/server/src/middleware.js.map +1 -0
  286. package/apps/web/.next/server/webpack-runtime.js +1 -0
  287. package/apps/web/.next/static/chunks/18-90b700ea37b686a2.js +1 -0
  288. package/apps/web/.next/static/chunks/87c73c54-24122e7b92478d00.js +1 -0
  289. package/apps/web/.next/static/chunks/9664-af80478aa73ba424.js +1 -0
  290. package/apps/web/.next/static/chunks/app/_not-found/page-b9cee17ed89ca24a.js +1 -0
  291. package/apps/web/.next/static/chunks/app/agents/[slug]/page-18369fc3fe1a9a7b.js +1 -0
  292. package/apps/web/.next/static/chunks/app/agents/new/page-bf11cf8901c7e2cd.js +1 -0
  293. package/apps/web/.next/static/chunks/app/api/agents/[id]/access/route-07f0f73ac9839899.js +1 -0
  294. package/apps/web/.next/static/chunks/app/api/agents/[id]/claude-md/route-07f0f73ac9839899.js +1 -0
  295. package/apps/web/.next/static/chunks/app/api/agents/[id]/logs/route-07f0f73ac9839899.js +1 -0
  296. package/apps/web/.next/static/chunks/app/api/agents/[id]/manifest/route-07f0f73ac9839899.js +1 -0
  297. package/apps/web/.next/static/chunks/app/api/agents/[id]/mcps/route-07f0f73ac9839899.js +1 -0
  298. package/apps/web/.next/static/chunks/app/api/agents/[id]/memories/[memId]/route-07f0f73ac9839899.js +1 -0
  299. package/apps/web/.next/static/chunks/app/api/agents/[id]/memories/route-07f0f73ac9839899.js +1 -0
  300. package/apps/web/.next/static/chunks/app/api/agents/[id]/permissions/route-07f0f73ac9839899.js +1 -0
  301. package/apps/web/.next/static/chunks/app/api/agents/[id]/reload/route-07f0f73ac9839899.js +1 -0
  302. package/apps/web/.next/static/chunks/app/api/agents/[id]/restrictions/route-07f0f73ac9839899.js +1 -0
  303. package/apps/web/.next/static/chunks/app/api/agents/[id]/route-07f0f73ac9839899.js +1 -0
  304. package/apps/web/.next/static/chunks/app/api/agents/[id]/skills/[skillId]/route-07f0f73ac9839899.js +1 -0
  305. package/apps/web/.next/static/chunks/app/api/agents/[id]/skills/route-07f0f73ac9839899.js +1 -0
  306. package/apps/web/.next/static/chunks/app/api/agents/[id]/slack-info/route-07f0f73ac9839899.js +1 -0
  307. package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/[sid]/restore/route-07f0f73ac9839899.js +1 -0
  308. package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/[sid]/route-07f0f73ac9839899.js +1 -0
  309. package/apps/web/.next/static/chunks/app/api/agents/[id]/snapshots/route-07f0f73ac9839899.js +1 -0
  310. package/apps/web/.next/static/chunks/app/api/agents/[id]/start/route-07f0f73ac9839899.js +1 -0
  311. package/apps/web/.next/static/chunks/app/api/agents/[id]/stop/route-07f0f73ac9839899.js +1 -0
  312. package/apps/web/.next/static/chunks/app/api/agents/route-07f0f73ac9839899.js +1 -0
  313. package/apps/web/.next/static/chunks/app/api/auth/login/route-07f0f73ac9839899.js +1 -0
  314. package/apps/web/.next/static/chunks/app/api/auth/logout/route-07f0f73ac9839899.js +1 -0
  315. package/apps/web/.next/static/chunks/app/api/auth/me/route-07f0f73ac9839899.js +1 -0
  316. package/apps/web/.next/static/chunks/app/api/auth/users/[id]/route-07f0f73ac9839899.js +1 -0
  317. package/apps/web/.next/static/chunks/app/api/auth/users/route-07f0f73ac9839899.js +1 -0
  318. package/apps/web/.next/static/chunks/app/api/env-vars/[key]/route-07f0f73ac9839899.js +1 -0
  319. package/apps/web/.next/static/chunks/app/api/env-vars/route-07f0f73ac9839899.js +1 -0
  320. package/apps/web/.next/static/chunks/app/api/jobs/[id]/route-07f0f73ac9839899.js +1 -0
  321. package/apps/web/.next/static/chunks/app/api/jobs/[id]/runs/route-07f0f73ac9839899.js +1 -0
  322. package/apps/web/.next/static/chunks/app/api/jobs/route-07f0f73ac9839899.js +1 -0
  323. package/apps/web/.next/static/chunks/app/api/mcps/[id]/route-07f0f73ac9839899.js +1 -0
  324. package/apps/web/.next/static/chunks/app/api/mcps/[id]/test/route-07f0f73ac9839899.js +1 -0
  325. package/apps/web/.next/static/chunks/app/api/mcps/route-07f0f73ac9839899.js +1 -0
  326. package/apps/web/.next/static/chunks/app/api/settings/route-07f0f73ac9839899.js +1 -0
  327. package/apps/web/.next/static/chunks/app/jobs/page-f5aa89a47c50efd8.js +1 -0
  328. package/apps/web/.next/static/chunks/app/layout-2079f4964aa7314e.js +1 -0
  329. package/apps/web/.next/static/chunks/app/login/layout-07f0f73ac9839899.js +1 -0
  330. package/apps/web/.next/static/chunks/app/login/page-aa259283dc38e8f9.js +1 -0
  331. package/apps/web/.next/static/chunks/app/page-e83437b608104dff.js +1 -0
  332. package/apps/web/.next/static/chunks/app/settings/env-vars/page-06479dbdfb78b76b.js +1 -0
  333. package/apps/web/.next/static/chunks/app/settings/mcps/page-75650686ed6490c7.js +1 -0
  334. package/apps/web/.next/static/chunks/app/settings/page-e1e62fc41ff6cddd.js +1 -0
  335. package/apps/web/.next/static/chunks/framework-811407f832a33072.js +1 -0
  336. package/apps/web/.next/static/chunks/main-3f1cddbdd67b1546.js +1 -0
  337. package/apps/web/.next/static/chunks/main-app-cebd8a6a5ccbf72d.js +1 -0
  338. package/apps/web/.next/static/chunks/pages/_app-50fa07b56b2d29ac.js +1 -0
  339. package/apps/web/.next/static/chunks/pages/_error-fed8688bdd23f211.js +1 -0
  340. package/apps/web/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  341. package/apps/web/.next/static/chunks/webpack-6c05566dba553c97.js +1 -0
  342. package/apps/web/.next/static/css/15371687405525e2.css +5 -0
  343. package/apps/web/.next/static/ikfNbLhuw7jntn35bz0lk/_buildManifest.js +1 -0
  344. package/apps/web/.next/static/ikfNbLhuw7jntn35bz0lk/_ssgManifest.js +1 -0
  345. package/apps/web/.next/trace +5 -0
  346. package/apps/web/.next/types/app/agents/[slug]/page.ts +84 -0
  347. package/apps/web/.next/types/app/agents/new/page.ts +84 -0
  348. package/apps/web/.next/types/app/api/agents/[id]/access/route.ts +347 -0
  349. package/apps/web/.next/types/app/api/agents/[id]/claude-md/route.ts +347 -0
  350. package/apps/web/.next/types/app/api/agents/[id]/logs/route.ts +347 -0
  351. package/apps/web/.next/types/app/api/agents/[id]/manifest/route.ts +347 -0
  352. package/apps/web/.next/types/app/api/agents/[id]/mcps/route.ts +347 -0
  353. package/apps/web/.next/types/app/api/agents/[id]/memories/[memId]/route.ts +347 -0
  354. package/apps/web/.next/types/app/api/agents/[id]/memories/route.ts +347 -0
  355. package/apps/web/.next/types/app/api/agents/[id]/permissions/route.ts +347 -0
  356. package/apps/web/.next/types/app/api/agents/[id]/reload/route.ts +347 -0
  357. package/apps/web/.next/types/app/api/agents/[id]/restrictions/route.ts +347 -0
  358. package/apps/web/.next/types/app/api/agents/[id]/route.ts +347 -0
  359. package/apps/web/.next/types/app/api/agents/[id]/skills/[skillId]/route.ts +347 -0
  360. package/apps/web/.next/types/app/api/agents/[id]/skills/route.ts +347 -0
  361. package/apps/web/.next/types/app/api/agents/[id]/slack-info/route.ts +347 -0
  362. package/apps/web/.next/types/app/api/agents/[id]/snapshots/[sid]/restore/route.ts +347 -0
  363. package/apps/web/.next/types/app/api/agents/[id]/snapshots/[sid]/route.ts +347 -0
  364. package/apps/web/.next/types/app/api/agents/[id]/snapshots/route.ts +347 -0
  365. package/apps/web/.next/types/app/api/agents/[id]/start/route.ts +347 -0
  366. package/apps/web/.next/types/app/api/agents/[id]/stop/route.ts +347 -0
  367. package/apps/web/.next/types/app/api/agents/route.ts +347 -0
  368. package/apps/web/.next/types/app/api/auth/login/route.ts +347 -0
  369. package/apps/web/.next/types/app/api/auth/logout/route.ts +347 -0
  370. package/apps/web/.next/types/app/api/auth/me/route.ts +347 -0
  371. package/apps/web/.next/types/app/api/auth/users/[id]/route.ts +347 -0
  372. package/apps/web/.next/types/app/api/auth/users/route.ts +347 -0
  373. package/apps/web/.next/types/app/api/env-vars/[key]/route.ts +347 -0
  374. package/apps/web/.next/types/app/api/env-vars/route.ts +347 -0
  375. package/apps/web/.next/types/app/api/jobs/[id]/route.ts +347 -0
  376. package/apps/web/.next/types/app/api/jobs/[id]/runs/route.ts +347 -0
  377. package/apps/web/.next/types/app/api/jobs/route.ts +347 -0
  378. package/apps/web/.next/types/app/api/mcps/[id]/route.ts +347 -0
  379. package/apps/web/.next/types/app/api/mcps/[id]/test/route.ts +347 -0
  380. package/apps/web/.next/types/app/api/mcps/route.ts +347 -0
  381. package/apps/web/.next/types/app/api/settings/route.ts +347 -0
  382. package/apps/web/.next/types/app/jobs/page.ts +84 -0
  383. package/apps/web/.next/types/app/login/layout.ts +84 -0
  384. package/apps/web/.next/types/app/login/page.ts +84 -0
  385. package/apps/web/.next/types/app/page.ts +84 -0
  386. package/apps/web/.next/types/app/settings/env-vars/page.ts +84 -0
  387. package/apps/web/.next/types/app/settings/mcps/page.ts +84 -0
  388. package/apps/web/.next/types/app/settings/page.ts +84 -0
  389. package/apps/web/.next/types/cache-life.d.ts +141 -0
  390. package/apps/web/.next/types/package.json +1 -0
  391. package/apps/web/.next/types/routes.d.ts +114 -0
  392. package/apps/web/.next/types/validator.ts +448 -0
  393. package/apps/web/Dockerfile +37 -0
  394. package/apps/web/next-env.d.ts +6 -0
  395. package/apps/web/next.config.js +6 -0
  396. package/apps/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  397. package/apps/web/package.json +48 -0
  398. package/apps/web/postcss.config.js +3 -0
  399. package/apps/web/public/logo.svg +17 -0
  400. package/apps/web/src/app/agents/[slug]/page.tsx +2235 -0
  401. package/apps/web/src/app/agents/new/page.tsx +1161 -0
  402. package/apps/web/src/app/api/agents/[id]/access/route.ts +76 -0
  403. package/apps/web/src/app/api/agents/[id]/claude-md/route.ts +111 -0
  404. package/apps/web/src/app/api/agents/[id]/logs/route.ts +84 -0
  405. package/apps/web/src/app/api/agents/[id]/manifest/route.ts +32 -0
  406. package/apps/web/src/app/api/agents/[id]/mcps/route.ts +73 -0
  407. package/apps/web/src/app/api/agents/[id]/memories/[memId]/route.ts +31 -0
  408. package/apps/web/src/app/api/agents/[id]/memories/route.ts +56 -0
  409. package/apps/web/src/app/api/agents/[id]/permissions/route.ts +74 -0
  410. package/apps/web/src/app/api/agents/[id]/reload/route.ts +33 -0
  411. package/apps/web/src/app/api/agents/[id]/restrictions/route.ts +85 -0
  412. package/apps/web/src/app/api/agents/[id]/route.ts +81 -0
  413. package/apps/web/src/app/api/agents/[id]/skills/[skillId]/route.ts +52 -0
  414. package/apps/web/src/app/api/agents/[id]/skills/route.ts +80 -0
  415. package/apps/web/src/app/api/agents/[id]/slack-info/route.ts +38 -0
  416. package/apps/web/src/app/api/agents/[id]/snapshots/[sid]/restore/route.ts +61 -0
  417. package/apps/web/src/app/api/agents/[id]/snapshots/[sid]/route.ts +53 -0
  418. package/apps/web/src/app/api/agents/[id]/snapshots/route.ts +84 -0
  419. package/apps/web/src/app/api/agents/[id]/start/route.ts +35 -0
  420. package/apps/web/src/app/api/agents/[id]/stop/route.ts +35 -0
  421. package/apps/web/src/app/api/agents/route.ts +99 -0
  422. package/apps/web/src/app/api/auth/login/route.ts +39 -0
  423. package/apps/web/src/app/api/auth/logout/route.ts +21 -0
  424. package/apps/web/src/app/api/auth/me/route.ts +24 -0
  425. package/apps/web/src/app/api/auth/users/[id]/route.ts +48 -0
  426. package/apps/web/src/app/api/auth/users/route.ts +63 -0
  427. package/apps/web/src/app/api/env-vars/[key]/route.ts +66 -0
  428. package/apps/web/src/app/api/env-vars/route.ts +59 -0
  429. package/apps/web/src/app/api/jobs/[id]/route.ts +51 -0
  430. package/apps/web/src/app/api/jobs/[id]/runs/route.ts +24 -0
  431. package/apps/web/src/app/api/jobs/route.ts +42 -0
  432. package/apps/web/src/app/api/mcps/[id]/route.ts +60 -0
  433. package/apps/web/src/app/api/mcps/[id]/test/route.ts +195 -0
  434. package/apps/web/src/app/api/mcps/route.ts +72 -0
  435. package/apps/web/src/app/api/settings/route.ts +42 -0
  436. package/apps/web/src/app/globals.css +124 -0
  437. package/apps/web/src/app/icon.svg +17 -0
  438. package/apps/web/src/app/jobs/page.tsx +543 -0
  439. package/apps/web/src/app/layout-shell.tsx +89 -0
  440. package/apps/web/src/app/layout.tsx +18 -0
  441. package/apps/web/src/app/login/layout.tsx +9 -0
  442. package/apps/web/src/app/login/page.tsx +150 -0
  443. package/apps/web/src/app/page.tsx +573 -0
  444. package/apps/web/src/app/settings/env-vars/page.tsx +216 -0
  445. package/apps/web/src/app/settings/mcps/page.tsx +763 -0
  446. package/apps/web/src/app/settings/page.tsx +528 -0
  447. package/apps/web/src/app/sidebar.tsx +345 -0
  448. package/apps/web/src/lib/__tests__/api-guard.test.ts +189 -0
  449. package/apps/web/src/lib/__tests__/auth.test.ts +262 -0
  450. package/apps/web/src/lib/__tests__/boss-registry.test.ts +323 -0
  451. package/apps/web/src/lib/__tests__/compile.test.ts +161 -0
  452. package/apps/web/src/lib/__tests__/db-agent-hierarchy.test.ts +136 -0
  453. package/apps/web/src/lib/__tests__/db-env-vars.test.ts +216 -0
  454. package/apps/web/src/lib/__tests__/db-restrictions.test.ts +117 -0
  455. package/apps/web/src/lib/__tests__/db.integration.test.ts +271 -0
  456. package/apps/web/src/lib/__tests__/diff.test.ts +102 -0
  457. package/apps/web/src/lib/__tests__/mcp-mask.test.ts +274 -0
  458. package/apps/web/src/lib/__tests__/skill-templates.test.ts +237 -0
  459. package/apps/web/src/lib/__tests__/slack-manifest.test.ts +105 -0
  460. package/apps/web/src/lib/api-guard.ts +68 -0
  461. package/apps/web/src/lib/auth-context.tsx +71 -0
  462. package/apps/web/src/lib/auth.ts +128 -0
  463. package/apps/web/src/lib/boss-registry.ts +90 -0
  464. package/apps/web/src/lib/compile.ts +51 -0
  465. package/apps/web/src/lib/db.ts +1196 -0
  466. package/apps/web/src/lib/diff.ts +43 -0
  467. package/apps/web/src/lib/mcp-mask.ts +91 -0
  468. package/apps/web/src/lib/portal.tsx +23 -0
  469. package/apps/web/src/lib/skill-templates.ts +148 -0
  470. package/apps/web/src/lib/slack-manifest.ts +85 -0
  471. package/apps/web/src/middleware.ts +68 -0
  472. package/apps/web/tailwind.config.js +6 -0
  473. package/apps/web/tsconfig.json +23 -0
  474. package/apps/web/vitest.config.mts +21 -0
  475. package/cli/.claude/settings.local.json +6 -0
  476. package/cli/README.md +281 -0
  477. package/cli/node_modules/.package-lock.json +427 -0
  478. package/cli/node_modules/commander/LICENSE +22 -0
  479. package/cli/node_modules/commander/Readme.md +1157 -0
  480. package/cli/node_modules/commander/esm.mjs +16 -0
  481. package/cli/node_modules/commander/index.js +24 -0
  482. package/cli/node_modules/commander/lib/argument.js +149 -0
  483. package/cli/node_modules/commander/lib/command.js +2509 -0
  484. package/cli/node_modules/commander/lib/error.js +39 -0
  485. package/cli/node_modules/commander/lib/help.js +520 -0
  486. package/cli/node_modules/commander/lib/option.js +330 -0
  487. package/cli/node_modules/commander/lib/suggestSimilar.js +101 -0
  488. package/cli/node_modules/commander/package-support.json +16 -0
  489. package/cli/node_modules/commander/package.json +84 -0
  490. package/cli/node_modules/commander/typings/esm.d.mts +3 -0
  491. package/cli/node_modules/commander/typings/index.d.ts +969 -0
  492. package/cli/package-lock.json +449 -0
  493. package/cli/package.json +44 -0
  494. package/cli/src/commands/init.ts +514 -0
  495. package/cli/src/commands/manage.ts +115 -0
  496. package/cli/src/index.ts +63 -0
  497. package/cli/tsconfig.json +14 -0
  498. package/docker-compose.yml +122 -0
  499. package/docs/agents/boss-agents.mdx +108 -0
  500. package/docs/agents/creating-agents.mdx +132 -0
  501. package/docs/agents/memory.mdx +113 -0
  502. package/docs/agents/tools.mdx +103 -0
  503. package/docs/configuration/env-vars.mdx +166 -0
  504. package/docs/configuration/mcp-servers.mdx +203 -0
  505. package/docs/configuration/slack-app.mdx +175 -0
  506. package/docs/docs.json +79 -0
  507. package/docs/favicon.svg +17 -0
  508. package/docs/features/history.mdx +60 -0
  509. package/docs/features/import-export.mdx +77 -0
  510. package/docs/features/logs.mdx +131 -0
  511. package/docs/features/multi-workspace.mdx +90 -0
  512. package/docs/features/scheduled-jobs.mdx +231 -0
  513. package/docs/features/users.mdx +92 -0
  514. package/docs/introduction.mdx +160 -0
  515. package/docs/logo/dark.svg +17 -0
  516. package/docs/logo/light.svg +17 -0
  517. package/docs/logo/wide-dark.svg +12 -0
  518. package/docs/logo/wide-light.svg +12 -0
  519. package/docs/quickstart.mdx +270 -0
  520. package/docs/self-hosting/docker.mdx +151 -0
  521. package/docs/self-hosting/production.mdx +176 -0
  522. package/package.json +20 -36
  523. package/packages/shared/dist/index.d.ts +8 -0
  524. package/packages/shared/dist/index.d.ts.map +1 -0
  525. package/packages/shared/dist/index.js +24 -0
  526. package/packages/shared/dist/index.js.map +1 -0
  527. package/packages/shared/dist/types.d.ts +584 -0
  528. package/packages/shared/dist/types.d.ts.map +1 -0
  529. package/packages/shared/dist/types.js +39 -0
  530. package/packages/shared/dist/types.js.map +1 -0
  531. package/packages/shared/package.json +15 -0
  532. package/packages/shared/src/db/schema.sql +354 -0
  533. package/packages/shared/src/index.ts +8 -0
  534. package/packages/shared/src/types.ts +683 -0
  535. package/packages/shared/tsconfig.json +17 -0
  536. package/scripts/dev.sh +45 -0
  537. /package/{dist → cli/dist}/commands/init.d.ts +0 -0
  538. /package/{dist → cli/dist}/commands/init.js +0 -0
  539. /package/{dist → cli/dist}/commands/manage.d.ts +0 -0
  540. /package/{dist → cli/dist}/commands/manage.js +0 -0
  541. /package/{dist → cli/dist}/index.d.ts +0 -0
  542. /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
+ }