@desplega.ai/agent-swarm 1.20.0 → 1.51.2

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 (561) hide show
  1. package/README.md +271 -169
  2. package/openapi.json +5015 -0
  3. package/package.json +40 -7
  4. package/plugin/commands/close-issue.md +7 -3
  5. package/plugin/commands/create-pr.md +18 -12
  6. package/plugin/commands/implement-issue.md +7 -3
  7. package/plugin/commands/respond-github.md +8 -4
  8. package/plugin/commands/review-pr.md +44 -10
  9. package/plugin/commands/start-leader.md +1 -3
  10. package/plugin/commands/start-worker.md +1 -3
  11. package/plugin/commands/work-on-task.md +22 -3
  12. package/plugin/pi-skills/close-issue/SKILL.md +90 -0
  13. package/plugin/pi-skills/create-pr/SKILL.md +99 -0
  14. package/plugin/pi-skills/implement-issue/SKILL.md +135 -0
  15. package/plugin/pi-skills/investigate-sentry-issue/SKILL.md +138 -0
  16. package/plugin/pi-skills/respond-github/SKILL.md +98 -0
  17. package/plugin/pi-skills/review-offered-task/SKILL.md +45 -0
  18. package/plugin/pi-skills/review-pr/SKILL.md +261 -0
  19. package/plugin/pi-skills/start-leader/SKILL.md +121 -0
  20. package/plugin/pi-skills/start-worker/SKILL.md +60 -0
  21. package/plugin/pi-skills/swarm-chat/SKILL.md +82 -0
  22. package/plugin/pi-skills/todos/SKILL.md +66 -0
  23. package/plugin/pi-skills/work-on-task/SKILL.md +65 -0
  24. package/plugin/skills/artifacts/examples/approval-flow.ts +34 -0
  25. package/plugin/skills/artifacts/examples/hono-dashboard.ts +31 -0
  26. package/plugin/skills/artifacts/examples/multi-artifact.ts +20 -0
  27. package/plugin/skills/artifacts/examples/static-report.sh +17 -0
  28. package/plugin/skills/artifacts/skill.md +71 -0
  29. package/src/agentmail/app.ts +65 -0
  30. package/src/agentmail/handlers.ts +262 -0
  31. package/src/agentmail/index.ts +9 -0
  32. package/src/agentmail/templates.ts +111 -0
  33. package/src/agentmail/types.ts +51 -0
  34. package/src/artifact-sdk/browser-sdk.ts +30 -0
  35. package/src/artifact-sdk/index.ts +2 -0
  36. package/src/artifact-sdk/localtunnel.d.ts +20 -0
  37. package/src/artifact-sdk/port.ts +12 -0
  38. package/src/artifact-sdk/server.ts +156 -0
  39. package/src/artifact-sdk/tunnel.ts +19 -0
  40. package/src/be/chunking.ts +193 -0
  41. package/src/be/db-queries/oauth.ts +90 -0
  42. package/src/be/db-queries/tracker.ts +182 -0
  43. package/src/be/db.ts +3327 -784
  44. package/src/be/embedding.ts +80 -0
  45. package/src/be/migrations/001_initial.sql +409 -0
  46. package/src/be/migrations/002_one_time_schedules.sql +59 -0
  47. package/src/be/migrations/003_workflows.sql +51 -0
  48. package/src/be/migrations/004_workflow_source.sql +81 -0
  49. package/src/be/migrations/005_epic_next_steps.sql +2 -0
  50. package/src/be/migrations/006_vcs_provider.sql +94 -0
  51. package/src/be/migrations/007_task_dir.sql +2 -0
  52. package/src/be/migrations/008_workflow_redesign.sql +85 -0
  53. package/src/be/migrations/009_tracker_integration.sql +144 -0
  54. package/src/be/migrations/010_step_diagnostics.sql +1 -0
  55. package/src/be/migrations/011_step_next_port.sql +1 -0
  56. package/src/be/migrations/012_trigger_schema.sql +1 -0
  57. package/src/be/migrations/013_task_output_schema.sql +2 -0
  58. package/src/be/migrations/014_prompt_templates.sql +33 -0
  59. package/src/be/migrations/015_workflow_workspace.sql +3 -0
  60. package/src/be/migrations/016_active_session_runner_session.sql +4 -0
  61. package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
  62. package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
  63. package/src/be/migrations/runner.ts +188 -0
  64. package/src/be/seed.ts +62 -0
  65. package/src/cli.tsx +231 -299
  66. package/src/commands/artifact.ts +241 -0
  67. package/src/commands/onboard/compose-generator.ts +169 -0
  68. package/src/commands/onboard/env-generator.ts +79 -0
  69. package/src/commands/onboard/manifest.ts +37 -0
  70. package/src/commands/onboard/presets.ts +85 -0
  71. package/src/commands/onboard/service-names.ts +47 -0
  72. package/src/commands/onboard/steps/core-credentials.tsx +111 -0
  73. package/src/commands/onboard/steps/custom-templates.tsx +168 -0
  74. package/src/commands/onboard/steps/generate.tsx +154 -0
  75. package/src/commands/onboard/steps/harness-credentials.tsx +195 -0
  76. package/src/commands/onboard/steps/harness.tsx +21 -0
  77. package/src/commands/onboard/steps/health-check.tsx +171 -0
  78. package/src/commands/onboard/steps/integration-github.tsx +105 -0
  79. package/src/commands/onboard/steps/integration-gitlab.tsx +79 -0
  80. package/src/commands/onboard/steps/integration-menu.tsx +58 -0
  81. package/src/commands/onboard/steps/integration-sentry.tsx +79 -0
  82. package/src/commands/onboard/steps/integration-slack.tsx +165 -0
  83. package/src/commands/onboard/steps/post-connect.tsx +145 -0
  84. package/src/commands/onboard/steps/post-dashboard.tsx +34 -0
  85. package/src/commands/onboard/steps/post-task.tsx +103 -0
  86. package/src/commands/onboard/steps/prereq-check.tsx +178 -0
  87. package/src/commands/onboard/steps/review.tsx +82 -0
  88. package/src/commands/onboard/steps/start.tsx +97 -0
  89. package/src/commands/onboard/templates.ts +34 -0
  90. package/src/commands/onboard/types.ts +259 -0
  91. package/src/commands/onboard.tsx +425 -0
  92. package/src/commands/runner.ts +1540 -630
  93. package/src/commands/setup.tsx +23 -38
  94. package/src/commands/shared/client-config.ts +41 -0
  95. package/src/commands/templates.ts +172 -0
  96. package/src/github/app.ts +8 -0
  97. package/src/github/handlers.ts +384 -151
  98. package/src/github/index.ts +1 -0
  99. package/src/github/mentions-aliases.test.ts +73 -0
  100. package/src/github/mentions.test.ts +3 -3
  101. package/src/github/mentions.ts +32 -6
  102. package/src/github/templates.ts +398 -0
  103. package/src/github/types.ts +1 -0
  104. package/src/gitlab/auth.ts +63 -0
  105. package/src/gitlab/handlers.ts +368 -0
  106. package/src/gitlab/index.ts +19 -0
  107. package/src/gitlab/reactions.ts +104 -0
  108. package/src/gitlab/templates.ts +140 -0
  109. package/src/gitlab/types.ts +130 -0
  110. package/src/heartbeat/heartbeat.ts +434 -0
  111. package/src/heartbeat/index.ts +1 -0
  112. package/src/heartbeat/templates.ts +30 -0
  113. package/src/hooks/hook.ts +555 -4
  114. package/src/hooks/tool-loop-detection.test.ts +158 -0
  115. package/src/hooks/tool-loop-detection.ts +167 -0
  116. package/src/http/active-sessions.ts +199 -0
  117. package/src/http/agents.ts +328 -0
  118. package/src/http/config.ts +191 -0
  119. package/src/http/core.ts +309 -0
  120. package/src/http/db-query.ts +91 -0
  121. package/src/http/ecosystem.ts +63 -0
  122. package/src/http/epics.ts +460 -0
  123. package/src/http/index.ts +216 -0
  124. package/src/http/mcp.ts +77 -0
  125. package/src/http/memory.ts +168 -0
  126. package/src/http/openapi.ts +109 -0
  127. package/src/http/poll.ts +299 -0
  128. package/src/http/prompt-templates.ts +412 -0
  129. package/src/http/repos.ts +195 -0
  130. package/src/http/route-def.ts +123 -0
  131. package/src/http/schedules.ts +426 -0
  132. package/src/http/session-data.ts +241 -0
  133. package/src/http/stats.ts +174 -0
  134. package/src/http/tasks.ts +468 -0
  135. package/src/http/trackers/index.ts +10 -0
  136. package/src/http/trackers/linear.ts +187 -0
  137. package/src/http/types.ts +12 -0
  138. package/src/http/utils.ts +87 -0
  139. package/src/http/webhooks.ts +432 -0
  140. package/src/http/workflows.ts +530 -0
  141. package/src/http.ts +1 -1890
  142. package/src/linear/README.md +65 -0
  143. package/src/linear/app.ts +48 -0
  144. package/src/linear/client.ts +18 -0
  145. package/src/linear/index.ts +1 -0
  146. package/src/linear/oauth.ts +35 -0
  147. package/src/linear/outbound.ts +212 -0
  148. package/src/linear/sync.ts +567 -0
  149. package/src/linear/templates.ts +47 -0
  150. package/src/linear/types.ts +7 -0
  151. package/src/linear/webhook.ts +104 -0
  152. package/src/oauth/README.md +66 -0
  153. package/src/oauth/index.ts +6 -0
  154. package/src/oauth/wrapper.ts +204 -0
  155. package/src/prompts/base-prompt.ts +150 -265
  156. package/src/prompts/defaults.ts +196 -0
  157. package/src/prompts/registry.ts +57 -0
  158. package/src/prompts/resolver.ts +296 -0
  159. package/src/prompts/session-templates.ts +604 -0
  160. package/src/providers/claude-adapter.ts +442 -0
  161. package/src/providers/index.ts +24 -0
  162. package/src/providers/pi-mono-adapter.ts +442 -0
  163. package/src/providers/pi-mono-extension.ts +624 -0
  164. package/src/providers/pi-mono-mcp-client.ts +124 -0
  165. package/src/providers/types.ts +75 -0
  166. package/src/scheduler/scheduler.test.ts +2 -0
  167. package/src/scheduler/scheduler.ts +231 -40
  168. package/src/server.ts +97 -6
  169. package/src/slack/HEURISTICS.md +105 -0
  170. package/src/slack/actions.ts +133 -0
  171. package/src/slack/app.ts +7 -0
  172. package/src/slack/assistant.ts +118 -0
  173. package/src/slack/blocks.ts +233 -0
  174. package/src/slack/channel-activity.ts +177 -0
  175. package/src/slack/commands.ts +31 -17
  176. package/src/slack/files.ts +1 -1
  177. package/src/slack/handlers.test.ts +114 -1
  178. package/src/slack/handlers.ts +230 -55
  179. package/src/slack/responses.ts +120 -67
  180. package/src/slack/router.ts +17 -99
  181. package/src/slack/templates.ts +55 -0
  182. package/src/slack/thread-buffer.ts +213 -0
  183. package/src/slack/watcher.ts +119 -4
  184. package/src/tests/agent-activity.test.ts +247 -0
  185. package/src/tests/agentmail-filters.test.ts +97 -0
  186. package/src/tests/artifact-sdk.test.ts +800 -0
  187. package/src/tests/base-prompt.test.ts +264 -0
  188. package/src/tests/build-pi-skills.test.ts +127 -0
  189. package/src/tests/channel-activity.test.ts +363 -0
  190. package/src/tests/claude-adapter.test.ts +126 -0
  191. package/src/tests/context-versioning.test.ts +425 -0
  192. package/src/tests/db-queries-oauth.test.ts +197 -0
  193. package/src/tests/db-queries-tracker.test.ts +230 -0
  194. package/src/tests/epics.test.ts +3 -3
  195. package/src/tests/error-tracker.test.ts +368 -0
  196. package/src/tests/fetch-resolved-env.test.ts +167 -0
  197. package/src/tests/generate-default-claude-md.test.ts +9 -1
  198. package/src/tests/generate-identity-templates.test.ts +124 -0
  199. package/src/tests/gitlab-auth.test.ts +109 -0
  200. package/src/tests/gitlab-handlers.test.ts +691 -0
  201. package/src/tests/gitlab-vcs-db.test.ts +177 -0
  202. package/src/tests/heartbeat.test.ts +364 -0
  203. package/src/tests/http-api-integration.test.ts +1698 -0
  204. package/src/tests/linear-outbound-sync.test.ts +200 -0
  205. package/src/tests/linear-webhook.test.ts +406 -0
  206. package/src/tests/match-route.test.ts +187 -0
  207. package/src/tests/memory.test.ts +737 -0
  208. package/src/tests/migration-runner-regressions.test.ts +86 -0
  209. package/src/tests/model-control.test.ts +338 -0
  210. package/src/tests/oauth-wrapper.test.ts +147 -0
  211. package/src/tests/onboard-compose.test.ts +138 -0
  212. package/src/tests/onboard-env.test.ts +174 -0
  213. package/src/tests/onboard-manifest.test.ts +137 -0
  214. package/src/tests/pi-mono-adapter.test.ts +234 -0
  215. package/src/tests/pool-session-logs.test.ts +199 -0
  216. package/src/tests/progress-dedup.test.ts +98 -0
  217. package/src/tests/prompt-template-github.test.ts +682 -0
  218. package/src/tests/prompt-template-remaining.test.ts +504 -0
  219. package/src/tests/prompt-template-resolver.test.ts +621 -0
  220. package/src/tests/prompt-template-session.test.ts +363 -0
  221. package/src/tests/prompt-templates-db.test.ts +616 -0
  222. package/src/tests/provider-adapter.test.ts +122 -0
  223. package/src/tests/provider-command-format.test.ts +98 -0
  224. package/src/tests/reload-config.test.ts +170 -0
  225. package/src/tests/runner-polling-api.test.ts +25 -20
  226. package/src/tests/scheduled-tasks.test.ts +104 -0
  227. package/src/tests/scheduler-backoff.test.ts +166 -0
  228. package/src/tests/self-improvement.test.ts +541 -0
  229. package/src/tests/session-attach.test.ts +536 -0
  230. package/src/tests/session-costs.test.ts +267 -1
  231. package/src/tests/slack-actions.test.ts +133 -0
  232. package/src/tests/slack-assistant.test.ts +136 -0
  233. package/src/tests/slack-blocks.test.ts +246 -0
  234. package/src/tests/slack-metadata-inheritance.test.ts +243 -0
  235. package/src/tests/slack-queue-offline.test.ts +174 -0
  236. package/src/tests/slack-router.test.ts +181 -0
  237. package/src/tests/slack-thread-buffer.test.ts +305 -0
  238. package/src/tests/slack-thread-followups.test.ts +298 -0
  239. package/src/tests/slack-watcher.test.ts +101 -0
  240. package/src/tests/structured-output.test.ts +307 -0
  241. package/src/tests/swarm-repos.test.ts +198 -0
  242. package/src/tests/task-cancellation.test.ts +6 -4
  243. package/src/tests/task-working-dir.test.ts +176 -0
  244. package/src/tests/template-fetch.test.ts +490 -0
  245. package/src/tests/tool-annotations.test.ts +371 -0
  246. package/src/tests/tracker-tools.test.ts +184 -0
  247. package/src/tests/update-profile-agentid.test.ts +248 -0
  248. package/src/tests/update-profile-api.test.ts +143 -3
  249. package/src/tests/update-profile-auth.test.ts +195 -0
  250. package/src/tests/validation-adapters.test.ts +86 -0
  251. package/src/tests/vcs-provider.test.ts +27 -0
  252. package/src/tests/workflow-agent-task.test.ts +196 -0
  253. package/src/tests/workflow-async-v2.test.ts +508 -0
  254. package/src/tests/workflow-convergence.test.ts +541 -0
  255. package/src/tests/workflow-definition-validation.test.ts +366 -0
  256. package/src/tests/workflow-engine-v2.test.ts +691 -0
  257. package/src/tests/workflow-executors.test.ts +736 -0
  258. package/src/tests/workflow-http-v2.test.ts +599 -0
  259. package/src/tests/workflow-integration-io.test.ts +902 -0
  260. package/src/tests/workflow-io-schemas.test.ts +624 -0
  261. package/src/tests/workflow-registry.test.ts +592 -0
  262. package/src/tests/workflow-retry-v2.test.ts +401 -0
  263. package/src/tests/workflow-retry-validation.test.ts +282 -0
  264. package/src/tests/workflow-schedule-trigger.test.ts +104 -0
  265. package/src/tests/workflow-template.test.ts +288 -0
  266. package/src/tests/workflow-trigger-schema.test.ts +359 -0
  267. package/src/tests/workflow-triggers-v2.test.ts +264 -0
  268. package/src/tests/workflow-versions.test.ts +208 -0
  269. package/src/tests/workflow-workspace.test.ts +272 -0
  270. package/src/tests/x402-client.test.ts +117 -0
  271. package/src/tests/x402-config.test.ts +182 -0
  272. package/src/tests/x402-spending-tracker.test.ts +185 -0
  273. package/src/tools/cancel-task.ts +2 -0
  274. package/src/tools/context-diff.ts +171 -0
  275. package/src/tools/context-history.ts +138 -0
  276. package/src/tools/create-channel.ts +1 -0
  277. package/src/tools/db-query.ts +78 -0
  278. package/src/tools/delete-channel.ts +132 -0
  279. package/src/tools/epics/assign-task-to-epic.ts +1 -0
  280. package/src/tools/epics/create-epic.ts +3 -2
  281. package/src/tools/epics/delete-epic.ts +2 -0
  282. package/src/tools/epics/get-epic-details.ts +2 -0
  283. package/src/tools/epics/list-epics.ts +2 -0
  284. package/src/tools/epics/unassign-task-from-epic.ts +1 -0
  285. package/src/tools/epics/update-epic.ts +7 -4
  286. package/src/tools/get-swarm.ts +2 -0
  287. package/src/tools/get-task-details.ts +2 -0
  288. package/src/tools/get-tasks.ts +27 -1
  289. package/src/tools/inject-learning.ts +106 -0
  290. package/src/tools/join-swarm.ts +17 -7
  291. package/src/tools/list-channels.ts +2 -0
  292. package/src/tools/list-services.ts +2 -0
  293. package/src/tools/memory-get.ts +56 -0
  294. package/src/tools/memory-search.ts +131 -0
  295. package/src/tools/my-agent-info.ts +2 -0
  296. package/src/tools/poll-task.ts +2 -20
  297. package/src/tools/post-message.ts +1 -0
  298. package/src/tools/prompt-templates/delete.ts +86 -0
  299. package/src/tools/prompt-templates/get.ts +89 -0
  300. package/src/tools/prompt-templates/index.ts +5 -0
  301. package/src/tools/prompt-templates/list.ts +95 -0
  302. package/src/tools/prompt-templates/preview.ts +84 -0
  303. package/src/tools/prompt-templates/set.ts +117 -0
  304. package/src/tools/read-messages.ts +2 -0
  305. package/src/tools/register-agentmail-inbox.ts +166 -0
  306. package/src/tools/register-service.ts +2 -0
  307. package/src/tools/schedules/create-schedule.ts +134 -24
  308. package/src/tools/schedules/delete-schedule.ts +2 -0
  309. package/src/tools/schedules/list-schedules.ts +20 -4
  310. package/src/tools/schedules/run-schedule-now.ts +1 -0
  311. package/src/tools/schedules/update-schedule.ts +49 -17
  312. package/src/tools/send-task.ts +132 -10
  313. package/src/tools/slack-download-file.ts +4 -2
  314. package/src/tools/slack-list-channels.ts +2 -0
  315. package/src/tools/slack-post.ts +2 -0
  316. package/src/tools/slack-read.ts +2 -0
  317. package/src/tools/slack-reply.ts +2 -0
  318. package/src/tools/slack-upload-file.ts +2 -0
  319. package/src/tools/store-progress.ts +205 -4
  320. package/src/tools/swarm-config/delete-config.ts +87 -0
  321. package/src/tools/swarm-config/get-config.ts +108 -0
  322. package/src/tools/swarm-config/index.ts +4 -0
  323. package/src/tools/swarm-config/list-config.ts +99 -0
  324. package/src/tools/swarm-config/set-config.ts +118 -0
  325. package/src/tools/task-action.ts +50 -5
  326. package/src/tools/task-dedup.ts +97 -0
  327. package/src/tools/templates.ts +53 -0
  328. package/src/tools/tool-config.ts +124 -0
  329. package/src/tools/tracker/index.ts +6 -0
  330. package/src/tools/tracker/tracker-link-epic.ts +64 -0
  331. package/src/tools/tracker/tracker-link-task.ts +64 -0
  332. package/src/tools/tracker/tracker-map-agent.ts +57 -0
  333. package/src/tools/tracker/tracker-status.ts +56 -0
  334. package/src/tools/tracker/tracker-sync-status.ts +42 -0
  335. package/src/tools/tracker/tracker-unlink.ts +41 -0
  336. package/src/tools/unregister-service.ts +2 -0
  337. package/src/tools/update-profile.ts +172 -17
  338. package/src/tools/update-service-status.ts +2 -0
  339. package/src/tools/utils.ts +10 -1
  340. package/src/tools/workflows/create-workflow.ts +129 -0
  341. package/src/tools/workflows/delete-workflow.ts +42 -0
  342. package/src/tools/workflows/get-workflow-run.ts +59 -0
  343. package/src/tools/workflows/get-workflow.ts +53 -0
  344. package/src/tools/workflows/index.ts +9 -0
  345. package/src/tools/workflows/list-workflow-runs.ts +48 -0
  346. package/src/tools/workflows/list-workflows.ts +42 -0
  347. package/src/tools/workflows/retry-workflow-run.ts +40 -0
  348. package/src/tools/workflows/trigger-workflow.ts +96 -0
  349. package/src/tools/workflows/update-workflow.ts +133 -0
  350. package/src/tracker/types.ts +51 -0
  351. package/src/types.ts +530 -14
  352. package/src/utils/credentials.test.ts +156 -0
  353. package/src/utils/credentials.ts +50 -0
  354. package/src/utils/error-tracker.ts +190 -0
  355. package/src/vcs/index.ts +15 -0
  356. package/src/vcs/types.ts +5 -0
  357. package/src/workflows/checkpoint.ts +121 -0
  358. package/src/workflows/cooldown.ts +28 -0
  359. package/src/workflows/definition.ts +235 -0
  360. package/src/workflows/engine.ts +580 -0
  361. package/src/workflows/event-bus.ts +29 -0
  362. package/src/workflows/executors/agent-task.ts +103 -0
  363. package/src/workflows/executors/base.ts +86 -0
  364. package/src/workflows/executors/code-match.ts +88 -0
  365. package/src/workflows/executors/index.ts +16 -0
  366. package/src/workflows/executors/notify.ts +93 -0
  367. package/src/workflows/executors/property-match.ts +104 -0
  368. package/src/workflows/executors/raw-llm.ts +83 -0
  369. package/src/workflows/executors/registry.ts +76 -0
  370. package/src/workflows/executors/script.ts +103 -0
  371. package/src/workflows/executors/validate.ts +215 -0
  372. package/src/workflows/executors/vcs.ts +58 -0
  373. package/src/workflows/index.ts +61 -0
  374. package/src/workflows/input.ts +46 -0
  375. package/src/workflows/json-schema-validator.ts +118 -0
  376. package/src/workflows/recovery.ts +139 -0
  377. package/src/workflows/resume.ts +229 -0
  378. package/src/workflows/retry-poller.ts +216 -0
  379. package/src/workflows/template.ts +74 -0
  380. package/src/workflows/templates.ts +86 -0
  381. package/src/workflows/triggers.ts +124 -0
  382. package/src/workflows/validation.ts +104 -0
  383. package/src/workflows/version.ts +44 -0
  384. package/src/x402/cli.ts +140 -0
  385. package/src/x402/client.ts +192 -0
  386. package/src/x402/config.ts +131 -0
  387. package/src/x402/index.ts +37 -0
  388. package/src/x402/openfort-signer.ts +83 -0
  389. package/src/x402/spending-tracker.ts +109 -0
  390. package/templates/official/coder/CLAUDE.md +49 -0
  391. package/templates/official/coder/IDENTITY.md +28 -0
  392. package/templates/official/coder/SOUL.md +43 -0
  393. package/templates/official/coder/TOOLS.md +40 -0
  394. package/templates/official/coder/config.json +23 -0
  395. package/templates/official/coder/start-up.sh +23 -0
  396. package/templates/official/content-reviewer/CLAUDE.md +68 -0
  397. package/templates/official/content-reviewer/IDENTITY.md +28 -0
  398. package/templates/official/content-reviewer/SOUL.md +44 -0
  399. package/templates/official/content-reviewer/TOOLS.md +37 -0
  400. package/templates/official/content-reviewer/config.json +23 -0
  401. package/templates/official/content-reviewer/start-up.sh +23 -0
  402. package/templates/official/content-strategist/CLAUDE.md +63 -0
  403. package/templates/official/content-strategist/IDENTITY.md +33 -0
  404. package/templates/official/content-strategist/SOUL.md +48 -0
  405. package/templates/official/content-strategist/TOOLS.md +47 -0
  406. package/templates/official/content-strategist/config.json +23 -0
  407. package/templates/official/content-strategist/start-up.sh +23 -0
  408. package/templates/official/content-writer/CLAUDE.md +72 -0
  409. package/templates/official/content-writer/IDENTITY.md +30 -0
  410. package/templates/official/content-writer/SOUL.md +46 -0
  411. package/templates/official/content-writer/TOOLS.md +44 -0
  412. package/templates/official/content-writer/config.json +23 -0
  413. package/templates/official/content-writer/start-up.sh +23 -0
  414. package/templates/official/forward-deployed-engineer/CLAUDE.md +54 -0
  415. package/templates/official/forward-deployed-engineer/IDENTITY.md +37 -0
  416. package/templates/official/forward-deployed-engineer/SOUL.md +55 -0
  417. package/templates/official/forward-deployed-engineer/config.json +21 -0
  418. package/templates/official/lead/CLAUDE.md +33 -0
  419. package/templates/official/lead/IDENTITY.md +36 -0
  420. package/templates/official/lead/SOUL.md +51 -0
  421. package/templates/official/lead/config.json +22 -0
  422. package/templates/official/researcher/CLAUDE.md +46 -0
  423. package/templates/official/researcher/IDENTITY.md +28 -0
  424. package/templates/official/researcher/SOUL.md +43 -0
  425. package/templates/official/researcher/config.json +21 -0
  426. package/templates/official/reviewer/CLAUDE.md +63 -0
  427. package/templates/official/reviewer/IDENTITY.md +28 -0
  428. package/templates/official/reviewer/SOUL.md +45 -0
  429. package/templates/official/reviewer/config.json +21 -0
  430. package/templates/official/tester/CLAUDE.md +53 -0
  431. package/templates/official/tester/IDENTITY.md +28 -0
  432. package/templates/official/tester/SOUL.md +55 -0
  433. package/templates/official/tester/config.json +21 -0
  434. package/templates/schema.ts +35 -0
  435. package/.claude/settings.local.json +0 -115
  436. package/.dockerignore +0 -61
  437. package/.editorconfig +0 -15
  438. package/.env.docker.example +0 -39
  439. package/.env.example +0 -40
  440. package/.github/workflows/ci.yml +0 -76
  441. package/.github/workflows/docker-and-deploy.yml +0 -117
  442. package/.wts-config.json +0 -4
  443. package/.wts-setup.ts +0 -102
  444. package/CLAUDE.md +0 -104
  445. package/CONTRIBUTING.md +0 -270
  446. package/DEPLOYMENT.md +0 -605
  447. package/Dockerfile +0 -57
  448. package/Dockerfile.worker +0 -157
  449. package/FAQ.md +0 -19
  450. package/MCP.md +0 -406
  451. package/UI.md +0 -40
  452. package/assets/agent-swarm-logo-orange.png +0 -0
  453. package/assets/agent-swarm-logo.png +0 -0
  454. package/assets/agent-swarm.mp4 +0 -0
  455. package/assets/agent-swarm.png +0 -0
  456. package/biome.json +0 -39
  457. package/deploy/DEPLOY.md +0 -60
  458. package/deploy/agent-swarm.service +0 -17
  459. package/deploy/docker-push.ts +0 -30
  460. package/deploy/install.ts +0 -85
  461. package/deploy/prod-db.ts +0 -42
  462. package/deploy/uninstall.ts +0 -12
  463. package/deploy/update.ts +0 -21
  464. package/docker-compose.example.yml +0 -159
  465. package/docker-entrypoint.sh +0 -352
  466. package/ecosystem.config.cjs +0 -66
  467. package/plugin/README.md +0 -1
  468. package/plugin/hooks/hooks.json +0 -71
  469. package/pyproject.toml +0 -9
  470. package/scripts/generate-mcp-docs.ts +0 -415
  471. package/slack-manifest.json +0 -71
  472. package/src/tests/get-inbox-message.test.ts +0 -145
  473. package/src/tools/get-inbox-message.ts +0 -89
  474. package/src/tools/inbox-delegate.ts +0 -113
  475. package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
  476. package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
  477. package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
  478. package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
  479. package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
  480. package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
  481. package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
  482. package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
  483. package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
  484. package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
  485. package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
  486. package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
  487. package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
  488. package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
  489. package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
  490. package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
  491. package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
  492. package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
  493. package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
  494. package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
  495. package/thoughts/shared/research/.gitkeep +0 -0
  496. package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
  497. package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
  498. package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
  499. package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
  500. package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
  501. package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
  502. package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
  503. package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
  504. package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
  505. package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
  506. package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
  507. package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
  508. package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
  509. package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
  510. package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
  511. package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
  512. package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
  513. package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
  514. package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
  515. package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
  516. package/tsconfig.json +0 -37
  517. package/ui/CLAUDE.md +0 -49
  518. package/ui/bun.lock +0 -771
  519. package/ui/index.html +0 -22
  520. package/ui/package-lock.json +0 -5290
  521. package/ui/package.json +0 -33
  522. package/ui/pnpm-lock.yaml +0 -3341
  523. package/ui/postcss.config.js +0 -6
  524. package/ui/public/logo.png +0 -0
  525. package/ui/src/App.tsx +0 -63
  526. package/ui/src/components/ActivityFeed.tsx +0 -440
  527. package/ui/src/components/AgentDetailPanel.tsx +0 -733
  528. package/ui/src/components/AgentsPanel.tsx +0 -815
  529. package/ui/src/components/ChatPanel.tsx +0 -1920
  530. package/ui/src/components/ConfigModal.tsx +0 -253
  531. package/ui/src/components/Dashboard.tsx +0 -832
  532. package/ui/src/components/EditAgentProfileModal.tsx +0 -433
  533. package/ui/src/components/EpicDetailPage.tsx +0 -741
  534. package/ui/src/components/EpicsPanel.tsx +0 -566
  535. package/ui/src/components/Header.tsx +0 -160
  536. package/ui/src/components/JsonViewer.tsx +0 -171
  537. package/ui/src/components/ScheduledTaskDetailPanel.tsx +0 -517
  538. package/ui/src/components/ScheduledTasksPanel.tsx +0 -639
  539. package/ui/src/components/ServicesPanel.tsx +0 -622
  540. package/ui/src/components/SessionLogPanel.tsx +0 -1219
  541. package/ui/src/components/StatsBar.tsx +0 -321
  542. package/ui/src/components/StatusBadge.tsx +0 -168
  543. package/ui/src/components/TaskDetailPanel.tsx +0 -903
  544. package/ui/src/components/TasksPanel.tsx +0 -614
  545. package/ui/src/components/UsageCharts.tsx +0 -216
  546. package/ui/src/components/UsageTab.tsx +0 -394
  547. package/ui/src/hooks/queries.ts +0 -353
  548. package/ui/src/hooks/useAutoScroll.ts +0 -83
  549. package/ui/src/index.css +0 -257
  550. package/ui/src/lib/api.ts +0 -268
  551. package/ui/src/lib/config.ts +0 -35
  552. package/ui/src/lib/contentPreview.ts +0 -208
  553. package/ui/src/lib/theme.ts +0 -214
  554. package/ui/src/lib/utils.ts +0 -88
  555. package/ui/src/main.tsx +0 -28
  556. package/ui/src/types/api.ts +0 -323
  557. package/ui/src/vite-env.d.ts +0 -1
  558. package/ui/tailwind.config.js +0 -37
  559. package/ui/tsconfig.json +0 -31
  560. package/ui/vite.config.ts +0 -35
  561. /package/{thoughts/shared/plans → templates/community}/.gitkeep +0 -0
@@ -0,0 +1,87 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { getActiveTaskCount } from "../be/db";
3
+
4
+ export function setCorsHeaders(res: ServerResponse) {
5
+ res.setHeader("Access-Control-Allow-Origin", "*");
6
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
7
+ res.setHeader("Access-Control-Allow-Headers", "*");
8
+ res.setHeader("Access-Control-Expose-Headers", "*");
9
+ }
10
+
11
+ export function parseQueryParams(url: string): URLSearchParams {
12
+ const queryIndex = url.indexOf("?");
13
+ if (queryIndex === -1) return new URLSearchParams();
14
+ return new URLSearchParams(url.slice(queryIndex + 1));
15
+ }
16
+
17
+ export function getPathSegments(url: string): string[] {
18
+ const pathEnd = url.indexOf("?");
19
+ const path = pathEnd === -1 ? url : url.slice(0, pathEnd);
20
+ return path.split("/").filter(Boolean);
21
+ }
22
+
23
+ /** Add capacity info to agent response */
24
+ export function agentWithCapacity<T extends { id: string; maxTasks?: number }>(
25
+ agent: T,
26
+ ): T & { capacity: { current: number; max: number; available: number } } {
27
+ const activeCount = getActiveTaskCount(agent.id);
28
+ const max = agent.maxTasks ?? 1;
29
+ return {
30
+ ...agent,
31
+ capacity: {
32
+ current: activeCount,
33
+ max,
34
+ available: Math.max(0, max - activeCount),
35
+ },
36
+ };
37
+ }
38
+
39
+ /** Parse JSON body from incoming request */
40
+ export async function parseBody<T = unknown>(req: IncomingMessage): Promise<T> {
41
+ const chunks: Buffer[] = [];
42
+ for await (const chunk of req) {
43
+ chunks.push(chunk as Buffer);
44
+ }
45
+ return JSON.parse(Buffer.concat(chunks).toString()) as T;
46
+ }
47
+
48
+ /** Send JSON response */
49
+ export function json(res: ServerResponse, data: unknown, status = 200) {
50
+ res.writeHead(status, { "Content-Type": "application/json" });
51
+ res.end(JSON.stringify(data));
52
+ }
53
+
54
+ /** Send error JSON response */
55
+ export function jsonError(res: ServerResponse, error: string, status = 400) {
56
+ res.writeHead(status, { "Content-Type": "application/json" });
57
+ res.end(JSON.stringify({ error }));
58
+ }
59
+
60
+ /**
61
+ * Match a route pattern against HTTP method and path segments.
62
+ *
63
+ * @param method - HTTP method from request (e.g. "GET", "POST")
64
+ * @param pathSegments - URL path segments (e.g. ["api", "config", "resolved"])
65
+ * @param expectedMethod - Expected HTTP method to match
66
+ * @param pattern - Segment patterns: string for literal match, null for dynamic param (must be truthy)
67
+ * @param exact - If true, ensures no extra trailing segments exist (default: false)
68
+ */
69
+ export function matchRoute(
70
+ method: string | undefined,
71
+ pathSegments: string[],
72
+ expectedMethod: string,
73
+ pattern: readonly (string | null)[],
74
+ exact = false,
75
+ ): boolean {
76
+ if (method !== expectedMethod) return false;
77
+ for (let i = 0; i < pattern.length; i++) {
78
+ const seg = pattern[i];
79
+ if (seg === null) {
80
+ if (!pathSegments[i]) return false;
81
+ } else {
82
+ if (pathSegments[i] !== seg) return false;
83
+ }
84
+ }
85
+ if (exact && pathSegments[pattern.length]) return false;
86
+ return true;
87
+ }
@@ -0,0 +1,432 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import type { AgentMailWebhookPayload } from "../agentmail";
3
+ import {
4
+ handleMessageReceived,
5
+ isAgentMailEnabled,
6
+ isInboxAllowed,
7
+ isSenderAllowed,
8
+ verifyAgentMailWebhook,
9
+ } from "../agentmail";
10
+ import type {
11
+ CheckRunEvent,
12
+ CheckSuiteEvent,
13
+ CommentEvent,
14
+ IssueEvent,
15
+ PullRequestEvent,
16
+ PullRequestReviewEvent,
17
+ WorkflowRunEvent,
18
+ } from "../github";
19
+ import {
20
+ handleCheckRun,
21
+ handleCheckSuite,
22
+ handleComment,
23
+ handleIssue,
24
+ handlePullRequest,
25
+ handlePullRequestReview,
26
+ handleWorkflowRun,
27
+ isGitHubEnabled,
28
+ verifyWebhookSignature,
29
+ } from "../github";
30
+ import type {
31
+ IssueEvent as GitLabIssueEvent,
32
+ MergeRequestEvent,
33
+ NoteEvent,
34
+ PipelineEvent,
35
+ } from "../gitlab";
36
+ import {
37
+ handleIssue as handleGitLabIssue,
38
+ handleMergeRequest,
39
+ handleNote,
40
+ handlePipeline,
41
+ isGitLabEnabled,
42
+ verifyGitLabWebhook,
43
+ } from "../gitlab";
44
+ import { workflowEventBus } from "../workflows/event-bus";
45
+ import { route } from "./route-def";
46
+
47
+ // ─── Route Definitions (documentation only — webhooks handle their own body parsing) ─
48
+
49
+ const githubWebhook = route({
50
+ method: "post",
51
+ path: "/api/github/webhook",
52
+ pattern: ["api", "github", "webhook"],
53
+ summary: "Handle GitHub webhook events",
54
+ tags: ["Webhooks"],
55
+ auth: { apiKey: false },
56
+ responses: {
57
+ 200: { description: "Event processed" },
58
+ 401: { description: "Invalid signature" },
59
+ 503: { description: "GitHub integration not configured" },
60
+ },
61
+ });
62
+
63
+ const gitlabWebhook = route({
64
+ method: "post",
65
+ path: "/api/gitlab/webhook",
66
+ pattern: ["api", "gitlab", "webhook"],
67
+ summary: "Handle GitLab webhook events",
68
+ tags: ["Webhooks"],
69
+ auth: { apiKey: false },
70
+ responses: {
71
+ 200: { description: "Event processed" },
72
+ 401: { description: "Invalid token" },
73
+ 503: { description: "GitLab integration not configured" },
74
+ },
75
+ });
76
+
77
+ const agentmailWebhook = route({
78
+ method: "post",
79
+ path: "/api/agentmail/webhook",
80
+ pattern: ["api", "agentmail", "webhook"],
81
+ summary: "Handle AgentMail webhook events",
82
+ tags: ["Webhooks"],
83
+ auth: { apiKey: false },
84
+ responses: {
85
+ 200: { description: "Event received" },
86
+ 401: { description: "Invalid signature" },
87
+ 503: { description: "AgentMail integration not configured" },
88
+ },
89
+ });
90
+
91
+ // ─── Handler ─────────────────────────────────────────────────────────────────
92
+
93
+ export async function handleWebhooks(
94
+ req: IncomingMessage,
95
+ res: ServerResponse,
96
+ pathSegments: string[],
97
+ ): Promise<boolean> {
98
+ // GitHub webhook — needs raw body for signature verification
99
+ if (githubWebhook.match(req.method, pathSegments)) {
100
+ if (!isGitHubEnabled()) {
101
+ res.writeHead(503, { "Content-Type": "application/json" });
102
+ res.end(JSON.stringify({ error: "GitHub integration not configured" }));
103
+ return true;
104
+ }
105
+
106
+ const eventType = req.headers["x-github-event"] as string | undefined;
107
+ const signature = req.headers["x-hub-signature-256"] as string | undefined;
108
+
109
+ const chunks: Buffer[] = [];
110
+ for await (const chunk of req) {
111
+ chunks.push(chunk);
112
+ }
113
+ const rawBody = Buffer.concat(chunks).toString();
114
+
115
+ const isValid = await verifyWebhookSignature(rawBody, signature ?? null);
116
+ if (!isValid) {
117
+ console.log("[GitHub] Invalid webhook signature");
118
+ res.writeHead(401, { "Content-Type": "application/json" });
119
+ res.end(JSON.stringify({ error: "Invalid signature" }));
120
+ return true;
121
+ }
122
+
123
+ if (eventType === "ping") {
124
+ console.log("[GitHub] Received ping event - webhook configured successfully");
125
+ res.writeHead(200, { "Content-Type": "application/json" });
126
+ res.end(JSON.stringify({ message: "pong" }));
127
+ return true;
128
+ }
129
+
130
+ let body: unknown;
131
+ try {
132
+ body = JSON.parse(rawBody);
133
+ } catch {
134
+ res.writeHead(400, { "Content-Type": "application/json" });
135
+ res.end(JSON.stringify({ error: "Invalid JSON body" }));
136
+ return true;
137
+ }
138
+
139
+ console.log(`[GitHub] Received ${eventType} event`);
140
+
141
+ let result: { created: boolean; taskId?: string } = { created: false };
142
+
143
+ try {
144
+ switch (eventType) {
145
+ case "pull_request":
146
+ result = await handlePullRequest(body as PullRequestEvent);
147
+ break;
148
+ case "issues":
149
+ result = await handleIssue(body as IssueEvent);
150
+ break;
151
+ case "issue_comment":
152
+ result = await handleComment(body as CommentEvent, "issue_comment");
153
+ break;
154
+ case "pull_request_review_comment":
155
+ result = await handleComment(body as CommentEvent, "pull_request_review_comment");
156
+ break;
157
+ case "pull_request_review":
158
+ result = await handlePullRequestReview(body as PullRequestReviewEvent);
159
+ break;
160
+ case "check_run":
161
+ result = await handleCheckRun(body as CheckRunEvent);
162
+ break;
163
+ case "check_suite":
164
+ result = await handleCheckSuite(body as CheckSuiteEvent);
165
+ break;
166
+ case "workflow_run":
167
+ result = await handleWorkflowRun(body as WorkflowRunEvent);
168
+ break;
169
+ default:
170
+ console.log(`[GitHub] Ignoring unsupported event type: ${eventType}`);
171
+ }
172
+
173
+ // Emit workflow trigger event for matching event types
174
+ switch (eventType) {
175
+ case "pull_request": {
176
+ const pr = body as unknown as PullRequestEvent;
177
+ workflowEventBus.emit(`github.pull_request.${pr.action}`, {
178
+ repo: pr.repository.full_name,
179
+ number: pr.pull_request.number,
180
+ title: pr.pull_request.title,
181
+ body: pr.pull_request.body,
182
+ action: pr.action,
183
+ merged: pr.pull_request.merged ?? false,
184
+ html_url: pr.pull_request.html_url,
185
+ user_login: pr.pull_request.user.login,
186
+ changed_files: pr.pull_request.changed_files,
187
+ });
188
+ break;
189
+ }
190
+ case "issues": {
191
+ const iss = body as unknown as IssueEvent;
192
+ workflowEventBus.emit(`github.issue.${iss.action}`, {
193
+ repo: iss.repository.full_name,
194
+ number: iss.issue.number,
195
+ title: iss.issue.title,
196
+ action: iss.action,
197
+ });
198
+ break;
199
+ }
200
+ case "issue_comment": {
201
+ const ic = body as unknown as CommentEvent;
202
+ workflowEventBus.emit("github.issue_comment.created", {
203
+ repo: ic.repository.full_name,
204
+ number: ic.issue?.number,
205
+ action: ic.action,
206
+ });
207
+ break;
208
+ }
209
+ case "pull_request_review": {
210
+ const prr = body as unknown as PullRequestReviewEvent;
211
+ workflowEventBus.emit("github.pull_request_review.submitted", {
212
+ repo: prr.repository.full_name,
213
+ number: prr.pull_request.number,
214
+ state: prr.review.state,
215
+ action: prr.action,
216
+ });
217
+ break;
218
+ }
219
+ }
220
+
221
+ res.writeHead(200, { "Content-Type": "application/json" });
222
+ res.end(JSON.stringify(result));
223
+ } catch (err) {
224
+ const errorMessage = err instanceof Error ? err.message : String(err);
225
+ console.error(`[GitHub] Error handling ${eventType} event: ${errorMessage}`);
226
+ if (err instanceof Error && err.stack) {
227
+ console.error(err.stack);
228
+ }
229
+ res.writeHead(500, { "Content-Type": "application/json" });
230
+ res.end(JSON.stringify({ error: "Internal server error", message: errorMessage }));
231
+ }
232
+ return true;
233
+ }
234
+
235
+ // GitLab webhook — needs raw body + custom token verification
236
+ if (gitlabWebhook.match(req.method, pathSegments)) {
237
+ if (!isGitLabEnabled()) {
238
+ res.writeHead(503, { "Content-Type": "application/json" });
239
+ res.end(JSON.stringify({ error: "GitLab integration not configured" }));
240
+ return true;
241
+ }
242
+
243
+ const token = req.headers["x-gitlab-token"] as string | undefined;
244
+ if (!verifyGitLabWebhook(token)) {
245
+ console.log("[GitLab] Invalid webhook token");
246
+ res.writeHead(401, { "Content-Type": "application/json" });
247
+ res.end(JSON.stringify({ error: "Invalid token" }));
248
+ return true;
249
+ }
250
+
251
+ const chunks: Buffer[] = [];
252
+ for await (const chunk of req) {
253
+ chunks.push(chunk);
254
+ }
255
+ const rawBody = Buffer.concat(chunks).toString();
256
+
257
+ let body: Record<string, unknown>;
258
+ try {
259
+ body = JSON.parse(rawBody);
260
+ } catch {
261
+ res.writeHead(400, { "Content-Type": "application/json" });
262
+ res.end(JSON.stringify({ error: "Invalid JSON body" }));
263
+ return true;
264
+ }
265
+
266
+ const objectKind = body.object_kind as string | undefined;
267
+ console.log(`[GitLab] Received ${objectKind} event`);
268
+
269
+ let result: { created: boolean; taskId?: string } = { created: false };
270
+
271
+ try {
272
+ switch (objectKind) {
273
+ case "merge_request":
274
+ result = await handleMergeRequest(body as unknown as MergeRequestEvent);
275
+ break;
276
+ case "issue":
277
+ result = await handleGitLabIssue(body as unknown as GitLabIssueEvent);
278
+ break;
279
+ case "note":
280
+ result = await handleNote(body as unknown as NoteEvent);
281
+ break;
282
+ case "pipeline":
283
+ result = await handlePipeline(body as unknown as PipelineEvent);
284
+ break;
285
+ default:
286
+ console.log(`[GitLab] Ignoring unsupported event type: ${objectKind}`);
287
+ }
288
+
289
+ // Emit workflow trigger events for GitLab
290
+ switch (objectKind) {
291
+ case "merge_request": {
292
+ const mr = body as unknown as MergeRequestEvent;
293
+ const action = mr.object_attributes.action;
294
+ workflowEventBus.emit(`gitlab.merge_request.${action}`, {
295
+ repo: mr.project.path_with_namespace,
296
+ number: mr.object_attributes.iid,
297
+ title: mr.object_attributes.title,
298
+ body: mr.object_attributes.description,
299
+ action,
300
+ merged: mr.object_attributes.state === "merged",
301
+ html_url: mr.object_attributes.url,
302
+ user_login: mr.user.username,
303
+ });
304
+ break;
305
+ }
306
+ case "issue": {
307
+ const iss = body as unknown as GitLabIssueEvent;
308
+ workflowEventBus.emit(`gitlab.issue.${iss.object_attributes.action}`, {
309
+ repo: iss.project.path_with_namespace,
310
+ number: iss.object_attributes.iid,
311
+ title: iss.object_attributes.title,
312
+ action: iss.object_attributes.action,
313
+ });
314
+ break;
315
+ }
316
+ case "note": {
317
+ const note = body as unknown as NoteEvent;
318
+ workflowEventBus.emit("gitlab.note.created", {
319
+ repo: note.project.path_with_namespace,
320
+ number: note.merge_request?.iid ?? note.issue?.iid,
321
+ action: "created",
322
+ });
323
+ break;
324
+ }
325
+ case "pipeline": {
326
+ const pl = body as unknown as PipelineEvent;
327
+ workflowEventBus.emit(`gitlab.pipeline.${pl.object_attributes.status}`, {
328
+ repo: pl.project.path_with_namespace,
329
+ number: pl.merge_request?.iid,
330
+ status: pl.object_attributes.status,
331
+ action: pl.object_attributes.status,
332
+ });
333
+ break;
334
+ }
335
+ }
336
+
337
+ res.writeHead(200, { "Content-Type": "application/json" });
338
+ res.end(JSON.stringify(result));
339
+ } catch (err) {
340
+ const errorMessage = err instanceof Error ? err.message : String(err);
341
+ console.error(`[GitLab] Error handling ${objectKind} event: ${errorMessage}`);
342
+ if (err instanceof Error && err.stack) {
343
+ console.error(err.stack);
344
+ }
345
+ res.writeHead(500, { "Content-Type": "application/json" });
346
+ res.end(JSON.stringify({ error: "Internal server error" }));
347
+ }
348
+ return true;
349
+ }
350
+
351
+ // AgentMail webhook — needs raw body for Svix signature verification
352
+ if (agentmailWebhook.match(req.method, pathSegments)) {
353
+ if (!isAgentMailEnabled()) {
354
+ res.writeHead(503, { "Content-Type": "application/json" });
355
+ res.end(JSON.stringify({ error: "AgentMail integration not configured" }));
356
+ return true;
357
+ }
358
+
359
+ const chunks: Buffer[] = [];
360
+ for await (const chunk of req) {
361
+ chunks.push(chunk);
362
+ }
363
+ const rawBody = Buffer.concat(chunks).toString();
364
+
365
+ const svixHeaders: Record<string, string> = {};
366
+ for (const key of ["svix-id", "svix-timestamp", "svix-signature"]) {
367
+ const value = req.headers[key];
368
+ if (typeof value === "string") {
369
+ svixHeaders[key] = value;
370
+ }
371
+ }
372
+
373
+ const verified = verifyAgentMailWebhook(rawBody, svixHeaders);
374
+ if (!verified) {
375
+ console.log("[AgentMail] Invalid webhook signature");
376
+ res.writeHead(401, { "Content-Type": "application/json" });
377
+ res.end(JSON.stringify({ error: "Invalid signature" }));
378
+ return true;
379
+ }
380
+
381
+ // Return 200 immediately — Svix best practice to avoid retries.
382
+ // Processing happens asynchronously below; dedup is handled in handlers.ts.
383
+ res.writeHead(200, { "Content-Type": "application/json" });
384
+ res.end(JSON.stringify({ received: true }));
385
+
386
+ const payload = verified as AgentMailWebhookPayload;
387
+
388
+ if (
389
+ payload.message &&
390
+ !isInboxAllowed(payload.message.inbox_id, process.env.AGENTMAIL_INBOX_DOMAIN_FILTER)
391
+ ) {
392
+ const domain = payload.message.inbox_id.split("@")[1] ?? "unknown";
393
+ console.log(
394
+ `[AgentMail] Ignoring event for inbox domain "${domain}" (not in AGENTMAIL_INBOX_DOMAIN_FILTER)`,
395
+ );
396
+ return true;
397
+ }
398
+
399
+ if (
400
+ payload.message &&
401
+ !isSenderAllowed(payload.message.from_, process.env.AGENTMAIL_SENDER_DOMAIN_FILTER)
402
+ ) {
403
+ const from = Array.isArray(payload.message.from_)
404
+ ? payload.message.from_.join(", ")
405
+ : payload.message.from_;
406
+ console.log(
407
+ `[AgentMail] Ignoring event from sender "${from}" (not in AGENTMAIL_SENDER_DOMAIN_FILTER)`,
408
+ );
409
+ return true;
410
+ }
411
+ console.log(`[AgentMail] Received ${payload.event_type} event (${payload.event_id})`);
412
+
413
+ try {
414
+ switch (payload.event_type) {
415
+ case "message.received":
416
+ await handleMessageReceived(payload);
417
+ break;
418
+ default:
419
+ console.log(`[AgentMail] Ignoring event type: ${payload.event_type}`);
420
+ }
421
+ } catch (err) {
422
+ const errorMessage = err instanceof Error ? err.message : String(err);
423
+ console.error(`[AgentMail] Error handling ${payload.event_type} event: ${errorMessage}`);
424
+ if (err instanceof Error && err.stack) {
425
+ console.error(err.stack);
426
+ }
427
+ }
428
+ return true;
429
+ }
430
+
431
+ return false;
432
+ }