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,604 @@
1
+ /**
2
+ * @fileoverview PostgreSQL database client for the runner service.
3
+ *
4
+ * Provides a singleton Pool instance and typed query helpers for all
5
+ * tables used by the runner: agents, mcp_servers, agent_mcps, skills,
6
+ * permissions, memories, and sessions.
7
+ *
8
+ * @module runner/db
9
+ */
10
+
11
+ import { Pool, PoolClient } from 'pg';
12
+ import { logger } from './logger';
13
+ import type {
14
+ Agent,
15
+ McpServer,
16
+ AgentMcp,
17
+ ScheduledJob,
18
+ Skill,
19
+ Permission,
20
+ Restriction,
21
+ Memory,
22
+ Session,
23
+ AgentStatus,
24
+ } from '@slackhive/shared';
25
+
26
+ /** Singleton Postgres connection pool. */
27
+ let pool: Pool | null = null;
28
+
29
+ /**
30
+ * Returns the singleton Postgres connection pool.
31
+ * Creates the pool on first call using DATABASE_URL from environment.
32
+ *
33
+ * @returns {Pool} The Postgres connection pool.
34
+ * @throws {Error} If DATABASE_URL is not set.
35
+ */
36
+ export function getPool(): Pool {
37
+ if (!pool) {
38
+ const databaseUrl = process.env.DATABASE_URL;
39
+ if (!databaseUrl) {
40
+ throw new Error('DATABASE_URL environment variable is required');
41
+ }
42
+ pool = new Pool({
43
+ connectionString: databaseUrl,
44
+ max: 10,
45
+ idleTimeoutMillis: 30_000,
46
+ connectionTimeoutMillis: 5_000,
47
+ });
48
+
49
+ pool.on('error', (err) => {
50
+ logger.error('Unexpected pool error', { error: (err as Error).message });
51
+ });
52
+ }
53
+ return pool;
54
+ }
55
+
56
+ /**
57
+ * Closes the Postgres connection pool.
58
+ * Should be called on graceful shutdown.
59
+ *
60
+ * @returns {Promise<void>}
61
+ */
62
+ export async function closePool(): Promise<void> {
63
+ if (pool) {
64
+ await pool.end();
65
+ pool = null;
66
+ }
67
+ }
68
+
69
+ // =============================================================================
70
+ // Row mappers — convert snake_case DB columns to camelCase TS interfaces
71
+ // =============================================================================
72
+
73
+ /**
74
+ * Maps a raw database row to an {@link Agent} interface.
75
+ *
76
+ * @param {Record<string, unknown>} row - Raw row from the agents table.
77
+ * @returns {Agent} Typed agent object.
78
+ */
79
+ function rowToAgent(row: Record<string, unknown>): Agent {
80
+ return {
81
+ id: row.id as string,
82
+ slug: row.slug as string,
83
+ name: row.name as string,
84
+ persona: row.persona as string | undefined,
85
+ description: row.description as string | undefined,
86
+ slackBotToken: row.slack_bot_token as string,
87
+ slackAppToken: row.slack_app_token as string,
88
+ slackSigningSecret: row.slack_signing_secret as string,
89
+ slackBotUserId: row.slack_bot_user_id as string | undefined,
90
+ model: row.model as string,
91
+ status: row.status as AgentStatus,
92
+ enabled: row.enabled !== false,
93
+ isBoss: row.is_boss as boolean,
94
+ reportsTo: (row.reports_to as string[]) ?? [],
95
+ claudeMd: (row.claude_md as string) ?? '',
96
+ createdBy: (row.created_by as string) ?? 'system',
97
+ createdAt: row.created_at as Date,
98
+ updatedAt: row.updated_at as Date,
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Maps a raw database row to a {@link McpServer} interface.
104
+ *
105
+ * @param {Record<string, unknown>} row - Raw row from the mcp_servers table.
106
+ * @returns {McpServer} Typed MCP server object.
107
+ */
108
+ function rowToMcpServer(row: Record<string, unknown>): McpServer {
109
+ return {
110
+ id: row.id as string,
111
+ name: row.name as string,
112
+ type: row.type as McpServer['type'],
113
+ config: row.config as McpServer['config'],
114
+ description: row.description as string | undefined,
115
+ enabled: row.enabled as boolean,
116
+ createdAt: row.created_at as Date,
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Maps a raw database row to a {@link Skill} interface.
122
+ *
123
+ * @param {Record<string, unknown>} row - Raw row from the skills table.
124
+ * @returns {Skill} Typed skill object.
125
+ */
126
+ function rowToSkill(row: Record<string, unknown>): Skill {
127
+ return {
128
+ id: row.id as string,
129
+ agentId: row.agent_id as string,
130
+ category: row.category as string,
131
+ filename: row.filename as string,
132
+ content: row.content as string,
133
+ sortOrder: row.sort_order as number,
134
+ createdAt: row.created_at as Date,
135
+ updatedAt: row.updated_at as Date,
136
+ };
137
+ }
138
+
139
+ /**
140
+ * Maps a raw database row to a {@link Permission} interface.
141
+ *
142
+ * @param {Record<string, unknown>} row - Raw row from the permissions table.
143
+ * @returns {Permission} Typed permission object.
144
+ */
145
+ function rowToPermission(row: Record<string, unknown>): Permission {
146
+ return {
147
+ id: row.id as string,
148
+ agentId: row.agent_id as string,
149
+ allowedTools: row.allowed_tools as string[],
150
+ deniedTools: row.denied_tools as string[],
151
+ updatedAt: row.updated_at as Date,
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Maps a raw database row to a {@link Memory} interface.
157
+ *
158
+ * @param {Record<string, unknown>} row - Raw row from the memories table.
159
+ * @returns {Memory} Typed memory object.
160
+ */
161
+ function rowToMemory(row: Record<string, unknown>): Memory {
162
+ return {
163
+ id: row.id as string,
164
+ agentId: row.agent_id as string,
165
+ type: row.type as Memory['type'],
166
+ name: row.name as string,
167
+ content: row.content as string,
168
+ createdAt: row.created_at as Date,
169
+ updatedAt: row.updated_at as Date,
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Maps a raw database row to a {@link Session} interface.
175
+ *
176
+ * @param {Record<string, unknown>} row - Raw row from the sessions table.
177
+ * @returns {Session} Typed session object.
178
+ */
179
+ function rowToSession(row: Record<string, unknown>): Session {
180
+ return {
181
+ id: row.id as string,
182
+ agentId: row.agent_id as string,
183
+ sessionKey: row.session_key as string,
184
+ claudeSessionId: row.claude_session_id as string | undefined,
185
+ mcpHash: row.mcp_hash as string | undefined,
186
+ lastActivity: row.last_activity as Date,
187
+ };
188
+ }
189
+
190
+ // =============================================================================
191
+ // Agent queries
192
+ // =============================================================================
193
+
194
+ /**
195
+ * Fetches all agents from the database.
196
+ *
197
+ * @returns {Promise<Agent[]>} All registered agents.
198
+ */
199
+ export async function getAllAgents(): Promise<Agent[]> {
200
+ const result = await getPool().query(
201
+ 'SELECT * FROM agents ORDER BY is_boss DESC, created_at ASC'
202
+ );
203
+ return result.rows.map(rowToAgent);
204
+ }
205
+
206
+ /**
207
+ * Fetches a single agent by ID.
208
+ *
209
+ * @param {string} id - Agent UUID.
210
+ * @returns {Promise<Agent | null>} The agent, or null if not found.
211
+ */
212
+ export async function getAgentById(id: string): Promise<Agent | null> {
213
+ const result = await getPool().query('SELECT * FROM agents WHERE id = $1', [id]);
214
+ return result.rows.length > 0 ? rowToAgent(result.rows[0]) : null;
215
+ }
216
+
217
+ /**
218
+ * Updates the runtime status of an agent.
219
+ *
220
+ * @param {string} id - Agent UUID.
221
+ * @param {AgentStatus} status - New status value.
222
+ * @returns {Promise<void>}
223
+ */
224
+ export async function updateAgentStatus(id: string, status: AgentStatus): Promise<void> {
225
+ await getPool().query(
226
+ 'UPDATE agents SET status = $1, updated_at = now() WHERE id = $2',
227
+ [status, id]
228
+ );
229
+ }
230
+
231
+ /**
232
+ * Updates the Slack bot user ID for an agent after successful auth.test.
233
+ *
234
+ * @param {string} id - Agent UUID.
235
+ * @param {string} slackBotUserId - The bot's Slack user ID (e.g., "U12345678").
236
+ * @returns {Promise<void>}
237
+ */
238
+ export async function updateAgentSlackUserId(id: string, slackBotUserId: string): Promise<void> {
239
+ await getPool().query(
240
+ 'UPDATE agents SET slack_bot_user_id = $1, updated_at = now() WHERE id = $2',
241
+ [slackBotUserId, id]
242
+ );
243
+ }
244
+
245
+ // =============================================================================
246
+ // MCP server queries
247
+ // =============================================================================
248
+
249
+ /**
250
+ * Fetches all MCP servers assigned to an agent, in catalog order.
251
+ *
252
+ * @param {string} agentId - Agent UUID.
253
+ * @returns {Promise<McpServer[]>} MCP servers assigned to this agent.
254
+ */
255
+ export async function getAgentMcpServers(agentId: string): Promise<McpServer[]> {
256
+ const result = await getPool().query(
257
+ `SELECT m.* FROM mcp_servers m
258
+ JOIN agent_mcps am ON am.mcp_id = m.id
259
+ WHERE am.agent_id = $1 AND m.enabled = true
260
+ ORDER BY m.name`,
261
+ [agentId]
262
+ );
263
+ return result.rows.map(rowToMcpServer);
264
+ }
265
+
266
+ // =============================================================================
267
+ // Skills queries
268
+ // =============================================================================
269
+
270
+ /**
271
+ * Fetches all skills for an agent, ordered for CLAUDE.md compilation.
272
+ * Skills are ordered by category (alphabetical) then sort_order (ascending).
273
+ *
274
+ * @param {string} agentId - Agent UUID.
275
+ * @returns {Promise<Skill[]>} Ordered skill files for this agent.
276
+ */
277
+ export async function getAgentSkills(agentId: string): Promise<Skill[]> {
278
+ const result = await getPool().query(
279
+ `SELECT * FROM skills
280
+ WHERE agent_id = $1
281
+ ORDER BY category ASC, sort_order ASC, filename ASC`,
282
+ [agentId]
283
+ );
284
+ return result.rows.map(rowToSkill);
285
+ }
286
+
287
+ /**
288
+ * Upserts a skill for an agent.
289
+ * Conflicts on (agent_id, category, filename) update content and sort_order.
290
+ *
291
+ * @param {string} agentId - Agent UUID.
292
+ * @param {string} category - Skill category directory (e.g. `'99-corrections'`).
293
+ * @param {string} filename - Skill filename (e.g. `'corrections.md'`).
294
+ * @param {string} content - Full markdown content of the skill.
295
+ * @param {number} [sortOrder=0] - Sort order within the category.
296
+ * @returns {Promise<Skill>} The upserted skill.
297
+ */
298
+ export async function upsertSkill(
299
+ agentId: string,
300
+ category: string,
301
+ filename: string,
302
+ content: string,
303
+ sortOrder = 0
304
+ ): Promise<Skill> {
305
+ const result = await getPool().query(
306
+ `INSERT INTO skills (agent_id, category, filename, content, sort_order)
307
+ VALUES ($1, $2, $3, $4, $5)
308
+ ON CONFLICT (agent_id, category, filename)
309
+ DO UPDATE SET content = EXCLUDED.content, sort_order = EXCLUDED.sort_order, updated_at = now()
310
+ RETURNING *`,
311
+ [agentId, category, filename, content, sortOrder]
312
+ );
313
+ return rowToSkill(result.rows[0]);
314
+ }
315
+
316
+ /**
317
+ * Deletes a skill by agent_id, category, and filename.
318
+ *
319
+ * @param {string} agentId - Agent UUID.
320
+ * @param {string} category - Skill category directory.
321
+ * @param {string} filename - Skill filename.
322
+ * @returns {Promise<boolean>} True if a row was deleted.
323
+ */
324
+ export async function deleteSkill(
325
+ agentId: string,
326
+ category: string,
327
+ filename: string,
328
+ ): Promise<boolean> {
329
+ const result = await getPool().query(
330
+ 'DELETE FROM skills WHERE agent_id = $1 AND category = $2 AND filename = $3',
331
+ [agentId, category, filename]
332
+ );
333
+ return (result.rowCount ?? 0) > 0;
334
+ }
335
+
336
+ // =============================================================================
337
+ // Permissions queries
338
+ // =============================================================================
339
+
340
+ /**
341
+ * Fetches the tool permissions for an agent.
342
+ *
343
+ * @param {string} agentId - Agent UUID.
344
+ * @returns {Promise<Permission | null>} The permission record, or null if not set.
345
+ */
346
+ export async function getAgentPermissions(agentId: string): Promise<Permission | null> {
347
+ const result = await getPool().query(
348
+ 'SELECT * FROM permissions WHERE agent_id = $1',
349
+ [agentId]
350
+ );
351
+ return result.rows.length > 0 ? rowToPermission(result.rows[0]) : null;
352
+ }
353
+
354
+ // =============================================================================
355
+ // Restrictions queries
356
+ // =============================================================================
357
+
358
+ function rowToRestriction(row: Record<string, unknown>): Restriction {
359
+ return {
360
+ id: row.id as string,
361
+ agentId: row.agent_id as string,
362
+ allowedChannels: (row.allowed_channels as string[]) ?? [],
363
+ updatedAt: row.updated_at as Date,
364
+ };
365
+ }
366
+
367
+ /**
368
+ * Fetches the channel restrictions for an agent.
369
+ *
370
+ * @param {string} agentId - Agent UUID.
371
+ * @returns {Promise<Restriction | null>} The restriction record, or null if not configured.
372
+ */
373
+ export async function getAgentRestrictions(agentId: string): Promise<Restriction | null> {
374
+ const result = await getPool().query(
375
+ 'SELECT * FROM agent_restrictions WHERE agent_id = $1',
376
+ [agentId]
377
+ );
378
+ return result.rows.length > 0 ? rowToRestriction(result.rows[0]) : null;
379
+ }
380
+
381
+ // =============================================================================
382
+ // Memory queries
383
+ // =============================================================================
384
+
385
+ /**
386
+ * Fetches all memory entries for an agent, ordered by type then created_at.
387
+ *
388
+ * @param {string} agentId - Agent UUID.
389
+ * @returns {Promise<Memory[]>} All memory entries for this agent.
390
+ */
391
+ export async function getAgentMemories(agentId: string): Promise<Memory[]> {
392
+ const result = await getPool().query(
393
+ `SELECT * FROM memories
394
+ WHERE agent_id = $1
395
+ ORDER BY type ASC, created_at ASC`,
396
+ [agentId]
397
+ );
398
+ return result.rows.map(rowToMemory);
399
+ }
400
+
401
+ /**
402
+ * Upserts a memory entry for an agent.
403
+ * If a memory with the same agent_id and name already exists, it is updated.
404
+ * Otherwise a new entry is created.
405
+ *
406
+ * This is called by the memory watcher when the agent writes new memory files
407
+ * to disk during a conversation.
408
+ *
409
+ * @param {string} agentId - Agent UUID.
410
+ * @param {Memory['type']} type - Memory type classification.
411
+ * @param {string} name - Unique name/identifier for this memory.
412
+ * @param {string} content - Full markdown content of the memory.
413
+ * @returns {Promise<Memory>} The upserted memory record.
414
+ */
415
+ export async function upsertMemory(
416
+ agentId: string,
417
+ type: Memory['type'],
418
+ name: string,
419
+ content: string
420
+ ): Promise<Memory> {
421
+ const result = await getPool().query(
422
+ `INSERT INTO memories (agent_id, type, name, content)
423
+ VALUES ($1, $2, $3, $4)
424
+ ON CONFLICT (agent_id, (name)) DO UPDATE
425
+ SET content = EXCLUDED.content,
426
+ type = EXCLUDED.type,
427
+ updated_at = now()
428
+ RETURNING *`,
429
+ [agentId, type, name, content]
430
+ );
431
+ return rowToMemory(result.rows[0]);
432
+ }
433
+
434
+ /**
435
+ * Upserts a memory entry by agent_id and name (no unique constraint version).
436
+ * Uses a safe upsert pattern compatible with the current schema.
437
+ *
438
+ * @param {string} agentId - Agent UUID.
439
+ * @param {Memory['type']} type - Memory type classification.
440
+ * @param {string} name - Memory name (used as identifier).
441
+ * @param {string} content - Full markdown content.
442
+ * @returns {Promise<void>}
443
+ */
444
+ export async function upsertMemorySafe(
445
+ agentId: string,
446
+ type: Memory['type'],
447
+ name: string,
448
+ content: string
449
+ ): Promise<void> {
450
+ await getPool().query(
451
+ `INSERT INTO memories (agent_id, type, name, content)
452
+ VALUES ($1, $2, $3, $4)
453
+ ON CONFLICT (agent_id, name) DO UPDATE
454
+ SET content = EXCLUDED.content,
455
+ type = EXCLUDED.type,
456
+ updated_at = now()`,
457
+ [agentId, type, name, content]
458
+ );
459
+ }
460
+
461
+ // =============================================================================
462
+ // Session queries
463
+ // =============================================================================
464
+
465
+ /**
466
+ * Fetches a conversation session by agent and session key.
467
+ *
468
+ * @param {string} agentId - Agent UUID.
469
+ * @param {string} sessionKey - Composite key: {userId}-{channelId}-{threadTs|'direct'}.
470
+ * @returns {Promise<Session | null>} The session, or null if not found.
471
+ */
472
+ export async function getSession(agentId: string, sessionKey: string): Promise<Session | null> {
473
+ const result = await getPool().query(
474
+ 'SELECT * FROM sessions WHERE agent_id = $1 AND session_key = $2',
475
+ [agentId, sessionKey]
476
+ );
477
+ return result.rows.length > 0 ? rowToSession(result.rows[0]) : null;
478
+ }
479
+
480
+ /**
481
+ * Creates or updates a conversation session.
482
+ * Updates last_activity on conflict.
483
+ *
484
+ * @param {string} agentId - Agent UUID.
485
+ * @param {string} sessionKey - Composite session key.
486
+ * @param {string | undefined} claudeSessionId - Claude Code SDK session ID.
487
+ * @returns {Promise<Session>} The upserted session.
488
+ */
489
+ export async function upsertSession(
490
+ agentId: string,
491
+ sessionKey: string,
492
+ claudeSessionId?: string,
493
+ mcpHash?: string
494
+ ): Promise<Session> {
495
+ const result = await getPool().query(
496
+ `INSERT INTO sessions (agent_id, session_key, claude_session_id, mcp_hash, last_activity)
497
+ VALUES ($1, $2, $3, $4, now())
498
+ ON CONFLICT (agent_id, session_key) DO UPDATE
499
+ SET claude_session_id = COALESCE(EXCLUDED.claude_session_id, sessions.claude_session_id),
500
+ mcp_hash = COALESCE(EXCLUDED.mcp_hash, sessions.mcp_hash),
501
+ last_activity = now()
502
+ RETURNING *`,
503
+ [agentId, sessionKey, claudeSessionId ?? null, mcpHash ?? null]
504
+ );
505
+ return rowToSession(result.rows[0]);
506
+ }
507
+
508
+ /**
509
+ * Deletes sessions for an agent that have been inactive for longer than maxAgeMs.
510
+ *
511
+ * @param {string} agentId - Agent UUID.
512
+ * @param {number} maxAgeMs - Maximum session age in milliseconds.
513
+ * @returns {Promise<number>} Number of sessions deleted.
514
+ */
515
+ export async function cleanupStaleSessions(agentId: string, maxAgeMs: number): Promise<number> {
516
+ const cutoff = new Date(Date.now() - maxAgeMs);
517
+ const result = await getPool().query(
518
+ 'DELETE FROM sessions WHERE agent_id = $1 AND last_activity < $2',
519
+ [agentId, cutoff]
520
+ );
521
+ return result.rowCount ?? 0;
522
+ }
523
+
524
+ // =============================================================================
525
+ // Scheduled Jobs
526
+ // =============================================================================
527
+
528
+ /**
529
+ * Returns all enabled scheduled jobs.
530
+ *
531
+ * @returns {Promise<ScheduledJob[]>}
532
+ */
533
+ export async function getAllEnabledJobs(): Promise<ScheduledJob[]> {
534
+ const r = await getPool().query('SELECT * FROM scheduled_jobs WHERE enabled = true');
535
+ return r.rows.map(row => ({
536
+ id: row.id,
537
+ agentId: row.agent_id,
538
+ name: row.name,
539
+ prompt: row.prompt,
540
+ cronSchedule: row.cron_schedule,
541
+ targetType: row.target_type,
542
+ targetId: row.target_id,
543
+ enabled: row.enabled,
544
+ createdAt: row.created_at,
545
+ updatedAt: row.updated_at,
546
+ }));
547
+ }
548
+
549
+ /**
550
+ * Inserts a new job run record with status 'running'.
551
+ *
552
+ * @param {string} jobId - The scheduled job ID.
553
+ * @returns {Promise<string>} The new run ID.
554
+ */
555
+ export async function insertJobRun(jobId: string): Promise<string> {
556
+ const r = await getPool().query(
557
+ "INSERT INTO job_runs (job_id, status) VALUES ($1, 'running') RETURNING id",
558
+ [jobId]
559
+ );
560
+ return r.rows[0].id;
561
+ }
562
+
563
+ /**
564
+ * Updates a job run with final status, output, and error.
565
+ *
566
+ * @param {string} runId - The run ID.
567
+ * @param {'success' | 'error'} status - Final status.
568
+ * @param {string | null} output - Truncated output text.
569
+ * @param {string | null} error - Error message if failed.
570
+ */
571
+ export async function updateJobRun(
572
+ runId: string,
573
+ status: 'success' | 'error',
574
+ output?: string | null,
575
+ error?: string | null
576
+ ): Promise<void> {
577
+ await getPool().query(
578
+ 'UPDATE job_runs SET status = $1, output = $2, error = $3, finished_at = now() WHERE id = $4',
579
+ [status, output ?? null, error ?? null, runId]
580
+ );
581
+ }
582
+
583
+ // =============================================================================
584
+ // Env Vars
585
+ // =============================================================================
586
+
587
+ /**
588
+ * Returns all env vars as a key→value map. Used by the runner to resolve
589
+ * envRefs in MCP stdio configs at agent start time.
590
+ *
591
+ * @returns {Promise<Record<string, string>>}
592
+ */
593
+ export async function getAllEnvVarValues(): Promise<Record<string, string>> {
594
+ const encKey = process.env.ENV_SECRET_KEY;
595
+ if (!encKey) {
596
+ logger.warn('ENV_SECRET_KEY not set — env var refs will not resolve');
597
+ return {};
598
+ }
599
+ const r = await getPool().query(
600
+ 'SELECT key, pgp_sym_decrypt(value::bytea, $1::text)::text AS value FROM env_vars',
601
+ [encKey],
602
+ );
603
+ return Object.fromEntries(r.rows.map((row: { key: string; value: string }) => [row.key, row.value]));
604
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview Entry point for the agent runner service.
3
+ *
4
+ * Loads environment variables, validates configuration, and starts the
5
+ * AgentRunner which manages all Slack bot instances.
6
+ *
7
+ * @module runner/index
8
+ */
9
+
10
+ import 'dotenv/config';
11
+ import { AgentRunner } from './agent-runner';
12
+ import { logger } from './logger';
13
+
14
+ /**
15
+ * Main entry point. Initializes and starts the AgentRunner.
16
+ *
17
+ * @returns {Promise<void>}
18
+ */
19
+ // Prevent a single bad agent from crashing the entire runner process.
20
+ // Individual agent errors are already logged and status set to 'error' in AgentRunner.
21
+ process.on('uncaughtException', (err) => {
22
+ logger.error('Uncaught exception — continuing', { error: err.message, stack: err.stack });
23
+ });
24
+ process.on('unhandledRejection', (reason) => {
25
+ logger.error('Unhandled rejection — continuing', { error: String(reason) });
26
+ });
27
+
28
+ async function main(): Promise<void> {
29
+ logger.info('Starting Slack Claude Code Agent Team — Runner Service');
30
+
31
+ if (!process.env.DATABASE_URL) {
32
+ logger.error('DATABASE_URL is required');
33
+ process.exit(1);
34
+ }
35
+
36
+ const runner = new AgentRunner();
37
+
38
+ try {
39
+ await runner.start();
40
+ } catch (err) {
41
+ logger.error('Failed to start AgentRunner', { error: (err as Error).message });
42
+ process.exit(1);
43
+ }
44
+ }
45
+
46
+ main();