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,573 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * @fileoverview Dashboard — agent fleet overview.
5
+ * Shows agent hierarchy by default (boss → reports) with grid toggle.
6
+ *
7
+ * @module web/app/page
8
+ */
9
+
10
+ import { useEffect, useState } from 'react';
11
+ import type { Agent } from '@slackhive/shared';
12
+ import Link from 'next/link';
13
+ import { useAuth } from '@/lib/auth-context';
14
+ import { Bot, LayoutGrid, GitBranch } from 'lucide-react';
15
+
16
+ const STATUS_COLOR: Record<string, string> = {
17
+ running: '#059669',
18
+ stopped: '#a3a3a3',
19
+ error: '#dc2626',
20
+ };
21
+
22
+ const STATUS_LABEL: Record<string, string> = {
23
+ running: 'Running',
24
+ stopped: 'Stopped',
25
+ error: 'Error',
26
+ };
27
+
28
+ export default function Dashboard() {
29
+ const [agents, setAgents] = useState<Agent[]>([]);
30
+ const [loading, setLoading] = useState(true);
31
+ const [title, setTitle] = useState('Welcome to SlackHive');
32
+ const [view, setView] = useState<'hierarchy' | 'grid'>('hierarchy');
33
+ const { canEdit } = useAuth();
34
+
35
+ useEffect(() => {
36
+ fetch('/api/agents')
37
+ .then(r => r.json())
38
+ .then(setAgents)
39
+ .finally(() => setLoading(false));
40
+ fetch('/api/settings')
41
+ .then(r => r.json())
42
+ .then((s: Record<string, string>) => { if (s.dashboardTitle) setTitle(s.dashboardTitle); })
43
+ .catch(() => {});
44
+ }, []);
45
+
46
+ const running = agents.filter(a => a.status === 'running').length;
47
+ const stopped = agents.filter(a => a.status === 'stopped').length;
48
+ const total = agents.length;
49
+ const bossCount = agents.filter(a => a.isBoss).length;
50
+
51
+ const hasHierarchy = agents.some(a => a.isBoss) || agents.some(a => a.reportsTo?.length > 0);
52
+
53
+ return (
54
+ <div style={{ padding: '36px 40px', maxWidth: 1200 }} className="fade-up responsive-pad">
55
+
56
+ {/* ── Header ───────────────────────────────────────────────────────── */}
57
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 28 }}>
58
+ <div>
59
+ <h1 style={{
60
+ margin: 0, fontSize: 26, fontWeight: 700,
61
+ letterSpacing: '-0.03em', color: 'var(--text)',
62
+ }}>
63
+ {title}
64
+ </h1>
65
+ <p style={{ margin: '6px 0 0', color: 'var(--muted)', fontSize: 14 }}>
66
+ {loading ? 'Loading agents…' : `${running} of ${total} agent${total !== 1 ? 's' : ''} online`}
67
+ </p>
68
+ </div>
69
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
70
+ {/* View toggle */}
71
+ {!loading && total > 0 && (
72
+ <div style={{
73
+ display: 'flex', alignItems: 'center',
74
+ background: 'var(--surface-2)', borderRadius: 8,
75
+ padding: 3, gap: 2,
76
+ border: '1px solid var(--border)',
77
+ }}>
78
+ <ViewBtn active={view === 'hierarchy'} onClick={() => setView('hierarchy')} title="Hierarchy">
79
+ <GitBranch size={14} />
80
+ </ViewBtn>
81
+ <ViewBtn active={view === 'grid'} onClick={() => setView('grid')} title="Grid">
82
+ <LayoutGrid size={14} />
83
+ </ViewBtn>
84
+ </div>
85
+ )}
86
+ {canEdit && (
87
+ <Link href="/agents/new" style={{
88
+ display: 'inline-flex', alignItems: 'center', gap: 7,
89
+ background: 'var(--accent)', color: '#fff',
90
+ padding: '10px 20px', borderRadius: 8,
91
+ fontSize: 13.5, fontWeight: 500, textDecoration: 'none',
92
+ boxShadow: 'var(--shadow-sm)',
93
+ transition: 'opacity 0.15s, transform 0.15s',
94
+ }}
95
+ onMouseEnter={e => { (e.currentTarget as HTMLElement).style.opacity = '0.85'; (e.currentTarget as HTMLElement).style.transform = 'translateY(-1px)'; }}
96
+ onMouseLeave={e => { (e.currentTarget as HTMLElement).style.opacity = '1'; (e.currentTarget as HTMLElement).style.transform = 'translateY(0)'; }}
97
+ >
98
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="none">
99
+ <path d="M8 3v10M3 8h10" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
100
+ </svg>
101
+ New Agent
102
+ </Link>
103
+ )}
104
+ </div>
105
+ </div>
106
+
107
+ {/* ── Stats ────────────────────────────────────────────────────────── */}
108
+ {!loading && total > 0 && (
109
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginBottom: 32 }} className="stagger stats-grid">
110
+ <StatCard label="Total" value={total} sub={`${total} agent${total !== 1 ? 's' : ''} registered`} />
111
+ <StatCard label="Running" value={running} color="#059669" sub={running > 0 ? 'All systems healthy' : 'None active'} />
112
+ <StatCard label="Stopped" value={stopped} color="#a3a3a3" sub={stopped > 0 ? `${stopped} offline` : 'All online'} />
113
+ <StatCard label="Boss" value={bossCount || '—'} color="#d97706" sub={bossCount > 0 ? `${bossCount} orchestrator${bossCount > 1 ? 's' : ''} active` : 'No boss assigned'} />
114
+ </div>
115
+ )}
116
+
117
+ {/* ── Content ──────────────────────────────────────────────────────── */}
118
+ {loading ? (
119
+ <SkeletonGrid />
120
+ ) : total === 0 ? (
121
+ <EmptyState />
122
+ ) : view === 'hierarchy' && hasHierarchy ? (
123
+ <HierarchyView agents={agents} />
124
+ ) : (
125
+ <GridView agents={agents} />
126
+ )}
127
+ </div>
128
+ );
129
+ }
130
+
131
+ // ── View toggle button ─────────────────────────────────────────────────────────
132
+
133
+ function ViewBtn({ active, onClick, title, children }: {
134
+ active: boolean; onClick: () => void; title: string; children: React.ReactNode;
135
+ }) {
136
+ return (
137
+ <button
138
+ onClick={onClick}
139
+ title={title}
140
+ style={{
141
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
142
+ width: 30, height: 30, borderRadius: 6, border: 'none',
143
+ background: active ? '#fff' : 'transparent',
144
+ color: active ? 'var(--text)' : 'var(--muted)',
145
+ cursor: 'pointer',
146
+ boxShadow: active ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
147
+ transition: 'all 0.15s',
148
+ }}
149
+ >
150
+ {children}
151
+ </button>
152
+ );
153
+ }
154
+
155
+ // ── Hierarchy view ────────────────────────────────────────────────────────────
156
+
157
+ const CARD_W = 260;
158
+ const CARD_GAP = 16;
159
+
160
+ function HierarchyView({ agents }: { agents: Agent[] }) {
161
+ const bosses = agents.filter(a => a.isBoss);
162
+ const nonBosses = agents.filter(a => !a.isBoss);
163
+ const standalone = nonBosses.filter(a => !a.reportsTo || a.reportsTo.length === 0);
164
+ const reportMap = new Map<string, Agent[]>();
165
+ for (const boss of bosses) {
166
+ reportMap.set(boss.id, nonBosses.filter(a => a.reportsTo?.includes(boss.id)));
167
+ }
168
+
169
+ if (bosses.length === 0) return <GridView agents={agents} label="All Agents" />;
170
+
171
+ return (
172
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 56 }}>
173
+ {bosses.map(boss => (
174
+ <OrgTree key={boss.id} boss={boss} reports={reportMap.get(boss.id) ?? []} />
175
+ ))}
176
+
177
+ {standalone.length > 0 && (
178
+ <div>
179
+ <SectionLabel label="Independent" />
180
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))', gap: 14 }}>
181
+ {standalone.map(a => <AgentCard key={a.id} agent={a} />)}
182
+ </div>
183
+ </div>
184
+ )}
185
+ </div>
186
+ );
187
+ }
188
+
189
+ function SectionLabel({ label }: { label: string }) {
190
+ return (
191
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 20 }}>
192
+ <div style={{ fontSize: 10, fontWeight: 700, letterSpacing: '0.09em', color: 'var(--subtle)', textTransform: 'uppercase' }}>
193
+ {label}
194
+ </div>
195
+ <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
196
+ </div>
197
+ );
198
+ }
199
+
200
+ function OrgTree({ boss, reports }: { boss: Agent; reports: Agent[] }) {
201
+ const n = reports.length;
202
+ // total width of the reports row
203
+ const rowW = n * CARD_W + Math.max(0, n - 1) * CARD_GAP;
204
+ const bossW = Math.min(360, Math.max(CARD_W, rowW));
205
+ const V_DROP = 32; // px from boss card bottom to horizontal bar
206
+ const STUB_H = 20; // px from horizontal bar down to each report card
207
+
208
+ return (
209
+ <div>
210
+ {/* Boss card — centered over the reports row */}
211
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: n > 0 ? 'center' : 'flex-start' }}>
212
+ <div style={{ width: bossW, maxWidth: '100%' }}>
213
+ <AgentCard agent={boss} highlight />
214
+ </div>
215
+
216
+ {n > 0 && (
217
+ <>
218
+ {/* SVG connector: vertical stem + horizontal bar + stubs */}
219
+ <svg
220
+ width={Math.max(rowW, bossW)}
221
+ height={V_DROP + STUB_H}
222
+ style={{ display: 'block', overflow: 'visible' }}
223
+ >
224
+ {(() => {
225
+ const svgW = Math.max(rowW, bossW);
226
+ const stemX = svgW / 2;
227
+ const barY = V_DROP;
228
+ // center of each report card
229
+ const cardCenters = Array.from({ length: n }, (_, i) =>
230
+ i * (CARD_W + CARD_GAP) + CARD_W / 2 + (svgW - rowW) / 2
231
+ );
232
+ const barX1 = cardCenters[0];
233
+ const barX2 = cardCenters[n - 1];
234
+ return (
235
+ <g stroke="var(--border-2)" strokeWidth="1.5" fill="none">
236
+ {/* Vertical stem from boss */}
237
+ <line x1={stemX} y1={0} x2={stemX} y2={barY} />
238
+ {/* Horizontal bar */}
239
+ {n > 1 && <line x1={barX1} y1={barY} x2={barX2} y2={barY} />}
240
+ {/* Stubs down to each card */}
241
+ {cardCenters.map((cx, i) => (
242
+ <line key={i} x1={cx} y1={barY} x2={cx} y2={barY + STUB_H} />
243
+ ))}
244
+ </g>
245
+ );
246
+ })()}
247
+ </svg>
248
+
249
+ {/* Reports row */}
250
+ <div style={{
251
+ display: 'flex', gap: CARD_GAP, alignItems: 'flex-start',
252
+ width: Math.max(rowW, bossW),
253
+ }}>
254
+ {/* Offset so cards align under SVG stubs */}
255
+ <div style={{
256
+ display: 'flex', gap: CARD_GAP,
257
+ marginLeft: (Math.max(rowW, bossW) - rowW) / 2,
258
+ }}>
259
+ {reports.map(agent => (
260
+ <div key={agent.id} style={{ width: CARD_W, flexShrink: 0 }}>
261
+ <AgentCard agent={agent} compact multiReport={(agent.reportsTo?.length ?? 0) > 1} />
262
+ </div>
263
+ ))}
264
+ </div>
265
+ </div>
266
+ </>
267
+ )}
268
+ </div>
269
+ </div>
270
+ );
271
+ }
272
+
273
+ // ── Grid view ─────────────────────────────────────────────────────────────────
274
+
275
+ function GridView({ agents, label = 'All Agents' }: { agents: Agent[]; label?: string }) {
276
+ return (
277
+ <>
278
+ <div style={{
279
+ fontSize: 11, fontWeight: 600, letterSpacing: '0.06em',
280
+ color: 'var(--subtle)', textTransform: 'uppercase',
281
+ marginBottom: 12, paddingLeft: 2,
282
+ }}>
283
+ {label}
284
+ </div>
285
+ <div style={{
286
+ display: 'grid',
287
+ gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
288
+ gap: 14,
289
+ }} className="stagger agent-grid">
290
+ {agents.map(agent => (
291
+ <AgentCard key={agent.id} agent={agent} />
292
+ ))}
293
+ </div>
294
+ </>
295
+ );
296
+ }
297
+
298
+ // ── Agent card ────────────────────────────────────────────────────────────────
299
+
300
+ function AgentCard({ agent, highlight, compact, multiReport }: {
301
+ agent: Agent;
302
+ highlight?: boolean;
303
+ compact?: boolean;
304
+ multiReport?: boolean;
305
+ }) {
306
+ const color = STATUS_COLOR[agent.status] ?? '#a3a3a3';
307
+
308
+ return (
309
+ <Link
310
+ href={`/agents/${agent.slug}`}
311
+ className="fade-up"
312
+ style={{
313
+ display: 'block', textDecoration: 'none',
314
+ background: '#fff',
315
+ border: highlight ? '1.5px solid rgba(217,119,6,0.25)' : 'none',
316
+ borderRadius: 'var(--radius-lg)',
317
+ padding: compact ? '14px 16px' : '22px 24px',
318
+ boxShadow: highlight
319
+ ? '0 0 0 1px rgba(217,119,6,0.12), var(--shadow-card)'
320
+ : 'var(--shadow-card)',
321
+ transition: 'box-shadow 0.2s cubic-bezier(0.16,1,0.3,1), transform 0.2s cubic-bezier(0.16,1,0.3,1)',
322
+ cursor: 'pointer',
323
+ position: 'relative',
324
+ overflow: 'hidden',
325
+ }}
326
+ onMouseEnter={e => {
327
+ const el = e.currentTarget as HTMLElement;
328
+ el.style.boxShadow = highlight
329
+ ? '0 0 0 1px rgba(217,119,6,0.2), var(--shadow-hover)'
330
+ : 'var(--shadow-hover)';
331
+ el.style.transform = 'translateY(-3px)';
332
+ }}
333
+ onMouseLeave={e => {
334
+ const el = e.currentTarget as HTMLElement;
335
+ el.style.boxShadow = highlight
336
+ ? '0 0 0 1px rgba(217,119,6,0.12), var(--shadow-card)'
337
+ : 'var(--shadow-card)';
338
+ el.style.transform = 'translateY(0)';
339
+ }}
340
+ >
341
+ {/* Boss accent bar */}
342
+ {agent.isBoss && (
343
+ <div style={{
344
+ position: 'absolute', top: 0, left: 0, right: 0, height: 2,
345
+ background: 'linear-gradient(90deg, #d97706, #f59e0b)',
346
+ }} />
347
+ )}
348
+
349
+ {/* Header */}
350
+ <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: compact ? 8 : 12 }}>
351
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
352
+ <div style={{
353
+ width: compact ? 30 : 36, height: compact ? 30 : 36,
354
+ borderRadius: compact ? 8 : 10, flexShrink: 0,
355
+ background: agent.isBoss ? '#171717' : 'var(--surface-2)',
356
+ border: agent.isBoss ? 'none' : '1px solid var(--border)',
357
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
358
+ fontSize: compact ? 12 : 14, fontWeight: 600,
359
+ color: agent.isBoss ? '#fff' : 'var(--text)',
360
+ }}>
361
+ {agent.name.charAt(0).toUpperCase()}
362
+ </div>
363
+ <div style={{ minWidth: 0 }}>
364
+ <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
365
+ <span style={{
366
+ fontSize: compact ? 13 : 14.5, fontWeight: 600, color: 'var(--text)',
367
+ letterSpacing: '-0.01em',
368
+ }}>
369
+ {agent.name}
370
+ </span>
371
+ {agent.isBoss && (
372
+ <span style={{
373
+ fontSize: 9.5, fontWeight: 600, letterSpacing: '0.04em',
374
+ background: 'rgba(217,119,6,0.1)', color: '#d97706',
375
+ padding: '2px 6px', borderRadius: 4,
376
+ textTransform: 'uppercase',
377
+ }}>Boss</span>
378
+ )}
379
+ {multiReport && (
380
+ <span style={{
381
+ fontSize: 9, fontWeight: 600, letterSpacing: '0.03em',
382
+ background: 'rgba(99,102,241,0.08)', color: '#6366f1',
383
+ padding: '2px 5px', borderRadius: 4,
384
+ }}>×2 bosses</span>
385
+ )}
386
+ </div>
387
+ <div style={{
388
+ fontSize: 11.5, color: 'var(--muted)',
389
+ fontFamily: 'var(--font-mono)',
390
+ }}>
391
+ @{agent.slug}
392
+ </div>
393
+ </div>
394
+ </div>
395
+
396
+ {/* Status */}
397
+ <div style={{
398
+ display: 'flex', alignItems: 'center', gap: 5,
399
+ flexShrink: 0, marginTop: 2,
400
+ }}>
401
+ <div
402
+ className={agent.status === 'running' ? 'status-running' : ''}
403
+ style={{ width: 7, height: 7, borderRadius: '50%', background: color }}
404
+ />
405
+ <span style={{ fontSize: 11.5, color, fontWeight: 500 }}>
406
+ {STATUS_LABEL[agent.status]}
407
+ </span>
408
+ </div>
409
+ </div>
410
+
411
+ {/* Description — hide in compact if no description */}
412
+ {(!compact || agent.description) && (
413
+ <p style={{
414
+ margin: `0 0 ${compact ? 10 : 16}px`, fontSize: 12.5, color: 'var(--muted)',
415
+ lineHeight: 1.55,
416
+ display: '-webkit-box', WebkitLineClamp: compact ? 1 : 2,
417
+ WebkitBoxOrient: 'vertical', overflow: 'hidden',
418
+ minHeight: compact ? 'auto' : 38,
419
+ }}>
420
+ {agent.description || (
421
+ <span style={{ color: 'var(--subtle)', fontStyle: 'italic' }}>No description</span>
422
+ )}
423
+ </p>
424
+ )}
425
+
426
+ {/* Footer */}
427
+ <div style={{
428
+ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
429
+ paddingTop: compact ? 10 : 14, borderTop: '1px solid var(--border)',
430
+ }}>
431
+ <span style={{
432
+ fontSize: 11, color: 'var(--muted)',
433
+ fontFamily: 'var(--font-mono)',
434
+ background: 'var(--surface-2)',
435
+ padding: '2px 7px', borderRadius: 4,
436
+ }}>
437
+ {agent.model.replace('claude-', '').split('-20')[0]}
438
+ </span>
439
+ <span style={{
440
+ fontSize: 11,
441
+ color: agent.slackBotUserId ? '#059669' : 'var(--subtle)',
442
+ display: 'flex', alignItems: 'center', gap: 4,
443
+ }}>
444
+ {agent.slackBotUserId ? (
445
+ <>
446
+ <div style={{ width: 5, height: 5, borderRadius: '50%', background: '#059669' }} />
447
+ Connected
448
+ </>
449
+ ) : 'Not connected'}
450
+ </span>
451
+ </div>
452
+ </Link>
453
+ );
454
+ }
455
+
456
+ // ── Stat card ─────────────────────────────────────────────────────────────────
457
+
458
+ function StatCard({ label, value, color, sub }: {
459
+ label: string; value: number | string; color?: string; sub?: string;
460
+ }) {
461
+ return (
462
+ <div className="fade-up" style={{
463
+ background: '#fff',
464
+ border: 'none',
465
+ borderRadius: 'var(--radius-lg)',
466
+ padding: '20px 24px',
467
+ boxShadow: 'var(--shadow-card)',
468
+ }}>
469
+ <div style={{
470
+ fontSize: 11, fontWeight: 600, letterSpacing: '0.05em',
471
+ color: 'var(--muted)', textTransform: 'uppercase', marginBottom: 8,
472
+ }}>
473
+ {label}
474
+ </div>
475
+ <div style={{
476
+ fontSize: 28, fontWeight: 700, color: color ?? 'var(--text)',
477
+ letterSpacing: '-0.03em', lineHeight: 1,
478
+ fontVariantNumeric: 'tabular-nums',
479
+ }}>
480
+ {value}
481
+ </div>
482
+ {sub && (
483
+ <div style={{ fontSize: 12, color: 'var(--subtle)', marginTop: 6 }}>
484
+ {sub}
485
+ </div>
486
+ )}
487
+ </div>
488
+ );
489
+ }
490
+
491
+ // ── Skeleton ──────────────────────────────────────────────────────────────────
492
+
493
+ function SkeletonGrid() {
494
+ return (
495
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 14 }}>
496
+ {[1, 2, 3].map(i => (
497
+ <div key={i} style={{
498
+ background: '#fff', borderRadius: 'var(--radius-lg)', padding: '22px 24px',
499
+ boxShadow: 'var(--shadow-card)', opacity: 1 - (i - 1) * 0.2,
500
+ }}>
501
+ <div style={{ display: 'flex', gap: 10, marginBottom: 16 }}>
502
+ <Skel w={36} h={36} r={10} />
503
+ <div style={{ flex: 1 }}>
504
+ <Skel w="55%" h={15} r={5} mb={6} />
505
+ <Skel w="35%" h={12} r={4} />
506
+ </div>
507
+ </div>
508
+ <Skel w="100%" h={12} r={4} mb={6} />
509
+ <Skel w="70%" h={12} r={4} />
510
+ </div>
511
+ ))}
512
+ </div>
513
+ );
514
+ }
515
+
516
+ function Skel({ w, h, r = 4, mb = 0 }: { w: number | string; h: number; r?: number; mb?: number }) {
517
+ return (
518
+ <div style={{
519
+ width: w, height: h, borderRadius: r,
520
+ background: 'var(--surface-2)', marginBottom: mb,
521
+ }} />
522
+ );
523
+ }
524
+
525
+ // ── Empty state ───────────────────────────────────────────────────────────────
526
+
527
+ function EmptyState() {
528
+ const { canEdit } = useAuth();
529
+ return (
530
+ <div style={{
531
+ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
532
+ minHeight: 400, gap: 20, textAlign: 'center',
533
+ }}>
534
+ <div style={{
535
+ width: 72, height: 72, borderRadius: 20,
536
+ background: 'var(--surface-2)', border: '1px solid var(--border)',
537
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
538
+ color: 'var(--muted)',
539
+ }}>
540
+ <Bot size={32} />
541
+ </div>
542
+ <div>
543
+ <p style={{
544
+ margin: '0 0 6px', fontSize: 18, fontWeight: 600,
545
+ color: 'var(--text)', letterSpacing: '-0.02em',
546
+ }}>
547
+ No agents yet
548
+ </p>
549
+ <p style={{ margin: 0, fontSize: 14, color: 'var(--muted)', maxWidth: 300 }}>
550
+ {canEdit ? 'Create your first Claude Code agent and connect it to Slack to get started.' : 'No agents have been configured yet. Ask an admin to set one up.'}
551
+ </p>
552
+ </div>
553
+ {canEdit && (
554
+ <Link href="/agents/new" style={{
555
+ display: 'inline-flex', alignItems: 'center', gap: 7,
556
+ background: 'var(--accent)', color: '#fff',
557
+ padding: '10px 22px', borderRadius: 8,
558
+ fontSize: 14, fontWeight: 500, textDecoration: 'none',
559
+ boxShadow: 'var(--shadow-sm)',
560
+ transition: 'opacity 0.15s',
561
+ }}
562
+ onMouseEnter={e => (e.currentTarget.style.opacity = '0.85')}
563
+ onMouseLeave={e => (e.currentTarget.style.opacity = '1')}
564
+ >
565
+ <svg width="14" height="14" viewBox="0 0 16 16" fill="none">
566
+ <path d="M8 3v10M3 8h10" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
567
+ </svg>
568
+ Create First Agent
569
+ </Link>
570
+ )}
571
+ </div>
572
+ );
573
+ }