@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,108 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import * as z from "zod";
3
+ import { getResolvedConfig, maskSecrets } from "@/be/db";
4
+ import { createToolRegistrar } from "@/tools/utils";
5
+ import { SwarmConfigSchema } from "@/types";
6
+
7
+ export const registerGetConfigTool = (server: McpServer) => {
8
+ createToolRegistrar(server)(
9
+ "get-config",
10
+ {
11
+ title: "Get Config",
12
+ description:
13
+ "Get resolved configuration values with scope resolution (repo > agent > global). Returns one entry per unique key with the most-specific scope winning. Use includeSecrets=true to see secret values.",
14
+ annotations: { readOnlyHint: true },
15
+
16
+ inputSchema: z.object({
17
+ agentId: z
18
+ .string()
19
+ .uuid()
20
+ .optional()
21
+ .describe("Agent ID for scope resolution. Omit for global-only configs."),
22
+ repoId: z
23
+ .string()
24
+ .uuid()
25
+ .optional()
26
+ .describe("Repo ID for scope resolution. Omit for agent/global-only configs."),
27
+ key: z
28
+ .string()
29
+ .optional()
30
+ .describe("Filter by specific key. If omitted, returns all resolved configs."),
31
+ includeSecrets: z
32
+ .boolean()
33
+ .optional()
34
+ .describe("If true, include actual secret values (default: false, secrets are masked)."),
35
+ }),
36
+ outputSchema: z.object({
37
+ yourAgentId: z.string().uuid().optional(),
38
+ success: z.boolean(),
39
+ message: z.string(),
40
+ configs: z.array(SwarmConfigSchema),
41
+ count: z.number(),
42
+ }),
43
+ },
44
+ async ({ agentId, repoId, key, includeSecrets }, requestInfo) => {
45
+ if (!requestInfo.agentId) {
46
+ return {
47
+ content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
48
+ structuredContent: {
49
+ success: false,
50
+ message: 'Agent ID not found. Set the "X-Agent-ID" header.',
51
+ configs: [],
52
+ count: 0,
53
+ },
54
+ };
55
+ }
56
+
57
+ try {
58
+ let configs = getResolvedConfig(agentId, repoId);
59
+
60
+ if (key) {
61
+ configs = configs.filter((c) => c.key === key);
62
+ }
63
+
64
+ const result = includeSecrets ? configs : maskSecrets(configs);
65
+ const count = result.length;
66
+
67
+ const configList =
68
+ count === 0
69
+ ? "No configs found."
70
+ : result
71
+ .map(
72
+ (c) =>
73
+ `- ${c.key}=${c.isSecret && !includeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""})`,
74
+ )
75
+ .join("\n");
76
+
77
+ return {
78
+ content: [
79
+ {
80
+ type: "text",
81
+ text:
82
+ count === 0 ? "No configs found." : `Found ${count} config(s):\n\n${configList}`,
83
+ },
84
+ ],
85
+ structuredContent: {
86
+ yourAgentId: requestInfo.agentId,
87
+ success: true,
88
+ message: count === 0 ? "No configs found." : `Found ${count} config(s).`,
89
+ configs: result,
90
+ count,
91
+ },
92
+ };
93
+ } catch (error) {
94
+ const message = error instanceof Error ? error.message : "Unknown error";
95
+ return {
96
+ content: [{ type: "text", text: `Failed to get config: ${message}` }],
97
+ structuredContent: {
98
+ yourAgentId: requestInfo.agentId,
99
+ success: false,
100
+ message: `Failed to get config: ${message}`,
101
+ configs: [],
102
+ count: 0,
103
+ },
104
+ };
105
+ }
106
+ },
107
+ );
108
+ };
@@ -0,0 +1,4 @@
1
+ export { registerDeleteConfigTool } from "./delete-config";
2
+ export { registerGetConfigTool } from "./get-config";
3
+ export { registerListConfigTool } from "./list-config";
4
+ export { registerSetConfigTool } from "./set-config";
@@ -0,0 +1,99 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import * as z from "zod";
3
+ import { getSwarmConfigs, maskSecrets } from "@/be/db";
4
+ import { createToolRegistrar } from "@/tools/utils";
5
+ import { SwarmConfigSchema, SwarmConfigScopeSchema } from "@/types";
6
+
7
+ export const registerListConfigTool = (server: McpServer) => {
8
+ createToolRegistrar(server)(
9
+ "list-config",
10
+ {
11
+ title: "List Config",
12
+ description:
13
+ "List raw config entries with optional filters. Unlike get-config, this returns raw entries without scope resolution — useful for seeing exactly what's configured at each scope level.",
14
+ annotations: { readOnlyHint: true },
15
+
16
+ inputSchema: z.object({
17
+ scope: SwarmConfigScopeSchema.optional().describe(
18
+ "Filter by scope: 'global', 'agent', or 'repo'.",
19
+ ),
20
+ scopeId: z.string().uuid().optional().describe("Filter by agent ID or repo ID."),
21
+ key: z.string().optional().describe("Filter by specific key."),
22
+ includeSecrets: z
23
+ .boolean()
24
+ .optional()
25
+ .describe("If true, include actual secret values (default: false)."),
26
+ }),
27
+ outputSchema: z.object({
28
+ yourAgentId: z.string().uuid().optional(),
29
+ success: z.boolean(),
30
+ message: z.string(),
31
+ configs: z.array(SwarmConfigSchema),
32
+ count: z.number(),
33
+ }),
34
+ },
35
+ async ({ scope, scopeId, key, includeSecrets }, requestInfo) => {
36
+ if (!requestInfo.agentId) {
37
+ return {
38
+ content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
39
+ structuredContent: {
40
+ success: false,
41
+ message: 'Agent ID not found. Set the "X-Agent-ID" header.',
42
+ configs: [],
43
+ count: 0,
44
+ },
45
+ };
46
+ }
47
+
48
+ try {
49
+ const configs = getSwarmConfigs({
50
+ scope,
51
+ scopeId,
52
+ key,
53
+ });
54
+
55
+ const result = includeSecrets ? configs : maskSecrets(configs);
56
+ const count = result.length;
57
+
58
+ const configList =
59
+ count === 0
60
+ ? "No configs found."
61
+ : result
62
+ .map(
63
+ (c) =>
64
+ `- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !includeSecrets ? "********" : c.value}${c.description ? ` — ${c.description}` : ""}`,
65
+ )
66
+ .join("\n");
67
+
68
+ return {
69
+ content: [
70
+ {
71
+ type: "text",
72
+ text:
73
+ count === 0 ? "No configs found." : `Found ${count} config(s):\n\n${configList}`,
74
+ },
75
+ ],
76
+ structuredContent: {
77
+ yourAgentId: requestInfo.agentId,
78
+ success: true,
79
+ message: count === 0 ? "No configs found." : `Found ${count} config(s).`,
80
+ configs: result,
81
+ count,
82
+ },
83
+ };
84
+ } catch (error) {
85
+ const message = error instanceof Error ? error.message : "Unknown error";
86
+ return {
87
+ content: [{ type: "text", text: `Failed to list configs: ${message}` }],
88
+ structuredContent: {
89
+ yourAgentId: requestInfo.agentId,
90
+ success: false,
91
+ message: `Failed to list configs: ${message}`,
92
+ configs: [],
93
+ count: 0,
94
+ },
95
+ };
96
+ }
97
+ },
98
+ );
99
+ };
@@ -0,0 +1,118 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import * as z from "zod";
3
+ import { maskSecrets, upsertSwarmConfig } from "@/be/db";
4
+ import { createToolRegistrar } from "@/tools/utils";
5
+ import { SwarmConfigSchema, SwarmConfigScopeSchema } from "@/types";
6
+
7
+ export const registerSetConfigTool = (server: McpServer) => {
8
+ createToolRegistrar(server)(
9
+ "set-config",
10
+ {
11
+ title: "Set Config",
12
+ description:
13
+ "Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses.",
14
+ annotations: { idempotentHint: true },
15
+
16
+ inputSchema: z.object({
17
+ scope: SwarmConfigScopeSchema.describe("Config scope: 'global', 'agent', or 'repo'."),
18
+ scopeId: z
19
+ .string()
20
+ .uuid()
21
+ .optional()
22
+ .describe(
23
+ "Agent ID or repo ID. Required for 'agent' and 'repo' scopes, omit for 'global'.",
24
+ ),
25
+ key: z
26
+ .string()
27
+ .min(1)
28
+ .max(255)
29
+ .describe("Configuration key (e.g., 'AGENTMAIL_WEBHOOK_SECRET')."),
30
+ value: z.string().describe("Configuration value."),
31
+ isSecret: z
32
+ .boolean()
33
+ .optional()
34
+ .describe("If true, value is masked in API responses (default: false)."),
35
+ envPath: z
36
+ .string()
37
+ .optional()
38
+ .describe("Optional: file path to write the value as KEY=VALUE in a .env file."),
39
+ description: z
40
+ .string()
41
+ .optional()
42
+ .describe("Optional human-readable description of this config entry."),
43
+ }),
44
+ outputSchema: z.object({
45
+ yourAgentId: z.string().uuid().optional(),
46
+ success: z.boolean(),
47
+ message: z.string(),
48
+ config: SwarmConfigSchema.optional(),
49
+ }),
50
+ },
51
+ async ({ scope, scopeId, key, value, isSecret, envPath, description }, requestInfo) => {
52
+ if (!requestInfo.agentId) {
53
+ return {
54
+ content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
55
+ structuredContent: {
56
+ success: false,
57
+ message: 'Agent ID not found. Set the "X-Agent-ID" header.',
58
+ },
59
+ };
60
+ }
61
+
62
+ try {
63
+ if (scope !== "global" && !scopeId) {
64
+ return {
65
+ content: [
66
+ {
67
+ type: "text",
68
+ text: `scopeId is required for scope '${scope}'. Provide an agent ID or repo ID.`,
69
+ },
70
+ ],
71
+ structuredContent: {
72
+ yourAgentId: requestInfo.agentId,
73
+ success: false,
74
+ message: `scopeId is required for scope '${scope}'.`,
75
+ },
76
+ };
77
+ }
78
+
79
+ const config = upsertSwarmConfig({
80
+ scope,
81
+ scopeId: scope === "global" ? null : scopeId,
82
+ key,
83
+ value,
84
+ isSecret,
85
+ envPath,
86
+ description,
87
+ });
88
+
89
+ const [masked] = maskSecrets([config]);
90
+
91
+ return {
92
+ content: [
93
+ {
94
+ type: "text",
95
+ text: `Config "${key}" set successfully (scope: ${scope}${scopeId ? `, scopeId: ${scopeId}` : ""}).`,
96
+ },
97
+ ],
98
+ structuredContent: {
99
+ yourAgentId: requestInfo.agentId,
100
+ success: true,
101
+ message: `Config "${key}" set successfully.`,
102
+ config: masked,
103
+ },
104
+ };
105
+ } catch (error) {
106
+ const message = error instanceof Error ? error.message : "Unknown error";
107
+ return {
108
+ content: [{ type: "text", text: `Failed to set config: ${message}` }],
109
+ structuredContent: {
110
+ yourAgentId: requestInfo.agentId,
111
+ success: false,
112
+ message: `Failed to set config: ${message}`,
113
+ },
114
+ };
115
+ }
116
+ },
117
+ );
118
+ };
@@ -5,6 +5,7 @@ import {
5
5
  checkDependencies,
6
6
  claimTask,
7
7
  createTaskExtended,
8
+ getActiveSessions,
8
9
  getActiveTaskCount,
9
10
  getAgentById,
10
11
  getDb,
@@ -12,8 +13,10 @@ import {
12
13
  hasCapacity,
13
14
  moveTaskFromBacklog,
14
15
  moveTaskToBacklog,
16
+ reassociateSessionLogs,
15
17
  rejectTask,
16
18
  releaseTask,
19
+ updateTaskClaudeSessionId,
17
20
  } from "@/be/db";
18
21
  import { createToolRegistrar } from "@/tools/utils";
19
22
  import { AgentTaskSchema } from "@/types";
@@ -33,6 +36,7 @@ export const registerTaskActionTool = (server: McpServer) => {
33
36
  "task-action",
34
37
  {
35
38
  title: "Task Pool Actions",
39
+ annotations: { destructiveHint: false },
36
40
  description:
37
41
  "Perform task pool operations: create unassigned tasks, claim/release tasks from pool, accept/reject offered tasks.",
38
42
  inputSchema: z.object({
@@ -58,6 +62,21 @@ export const registerTaskActionTool = (server: McpServer) => {
58
62
  taskId: z.uuid().optional().describe("Task ID (required for claim/release/accept/reject)."),
59
63
  // For 'reject' action:
60
64
  reason: z.string().optional().describe("Reason for rejection (optional for 'reject')."),
65
+ // For 'create' action:
66
+ dir: z
67
+ .string()
68
+ .min(1)
69
+ .startsWith("/")
70
+ .optional()
71
+ .describe(
72
+ "Working directory (absolute path) for the agent to start in. Only used with 'create' action.",
73
+ ),
74
+ model: z
75
+ .enum(["haiku", "sonnet", "opus"])
76
+ .optional()
77
+ .describe(
78
+ "Model to use for the created task ('haiku', 'sonnet', or 'opus'). Only used with 'create' action.",
79
+ ),
61
80
  }),
62
81
  outputSchema: z.object({
63
82
  yourAgentId: z.string().uuid().optional(),
@@ -67,7 +86,8 @@ export const registerTaskActionTool = (server: McpServer) => {
67
86
  }),
68
87
  },
69
88
  async (input, requestInfo, _meta) => {
70
- const { action, task, taskType, tags, priority, dependsOn, taskId, reason } = input;
89
+ const { action, task, taskType, tags, priority, dependsOn, taskId, reason, dir, model } =
90
+ input;
71
91
 
72
92
  if (!requestInfo.agentId) {
73
93
  return {
@@ -96,6 +116,8 @@ export const registerTaskActionTool = (server: McpServer) => {
96
116
  tags,
97
117
  priority,
98
118
  dependsOn,
119
+ dir,
120
+ model,
99
121
  });
100
122
  return {
101
123
  success: true,
@@ -117,6 +139,8 @@ export const registerTaskActionTool = (server: McpServer) => {
117
139
  message: `You have no capacity (${activeCount}/${agent?.maxTasks ?? 1} tasks). Complete a task first.`,
118
140
  };
119
141
  }
142
+ // Pre-checks for informative error messages (the atomic UPDATE in
143
+ // claimTask is the real guard against race conditions)
120
144
  const existingTask = getTaskById(taskId);
121
145
  if (!existingTask) {
122
146
  return { success: false, message: `Task "${taskId}" not found.` };
@@ -124,7 +148,7 @@ export const registerTaskActionTool = (server: McpServer) => {
124
148
  if (existingTask.status !== "unassigned") {
125
149
  return {
126
150
  success: false,
127
- message: `Task "${taskId}" is not unassigned (status: ${existingTask.status}).`,
151
+ message: `Task "${taskId}" is not unassigned (status: ${existingTask.status}). It may have been claimed by another agent.`,
128
152
  };
129
153
  }
130
154
  // Check if task dependencies are met
@@ -135,10 +159,31 @@ export const registerTaskActionTool = (server: McpServer) => {
135
159
  message: `Task "${taskId}" has unmet dependencies: ${blockedBy.join(", ")}. Cannot claim until dependencies are completed.`,
136
160
  };
137
161
  }
162
+ // Atomic claim — only one agent can win this race
138
163
  const claimedTask = claimTask(taskId, agentId);
139
164
  if (!claimedTask) {
140
- return { success: false, message: `Failed to claim task "${taskId}".` };
165
+ return {
166
+ success: false,
167
+ message: `Task "${taskId}" was already claimed by another agent. Try a different task.`,
168
+ };
169
+ }
170
+
171
+ // Reassociate session logs from pool trigger's random UUID to real task ID
172
+ const sessions = getActiveSessions(agentId);
173
+ const activeSession = sessions.find((s) => s.runnerSessionId);
174
+ if (activeSession?.runnerSessionId) {
175
+ const count = reassociateSessionLogs(activeSession.runnerSessionId, taskId);
176
+ if (count > 0) {
177
+ console.log(
178
+ `[task-action] Reassociated ${count} session logs for claimed task ${taskId.slice(0, 8)}`,
179
+ );
180
+ }
181
+ // Propagate provider session ID (e.g. claudeSessionId) to the task
182
+ if (activeSession.providerSessionId) {
183
+ updateTaskClaudeSessionId(taskId, activeSession.providerSessionId);
184
+ }
141
185
  }
186
+
142
187
  return {
143
188
  success: true,
144
189
  message: `Claimed task "${taskId}".`,
@@ -157,10 +202,10 @@ export const registerTaskActionTool = (server: McpServer) => {
157
202
  if (existingTask.agentId !== agentId) {
158
203
  return { success: false, message: `Task "${taskId}" is not assigned to you.` };
159
204
  }
160
- if (existingTask.status !== "pending") {
205
+ if (existingTask.status !== "pending" && existingTask.status !== "in_progress") {
161
206
  return {
162
207
  success: false,
163
- message: `Cannot release task in status "${existingTask.status}". Only 'pending' tasks can be released.`,
208
+ message: `Cannot release task in status "${existingTask.status}". Only 'pending' or 'in_progress' tasks can be released.`,
164
209
  };
165
210
  }
166
211
  const releasedTask = releaseTask(taskId);
@@ -0,0 +1,97 @@
1
+ import { findRecentSimilarTasks } from "@/be/db";
2
+ import type { AgentTask } from "@/types";
3
+
4
+ /**
5
+ * Jaccard similarity on word sets.
6
+ * Tokenizes both strings into lowercase word sets and computes |intersection| / |union|.
7
+ */
8
+ export function jaccardSimilarity(a: string, b: string): number {
9
+ const tokenize = (s: string) =>
10
+ new Set(
11
+ s
12
+ .toLowerCase()
13
+ .replace(/[^\w\s]/g, " ")
14
+ .split(/\s+/)
15
+ .filter((w) => w.length > 0),
16
+ );
17
+
18
+ const wordsA = tokenize(a);
19
+ const wordsB = tokenize(b);
20
+
21
+ if (wordsA.size === 0 && wordsB.size === 0) return 1;
22
+ if (wordsA.size === 0 || wordsB.size === 0) return 0;
23
+
24
+ let intersection = 0;
25
+ for (const w of wordsA) {
26
+ if (wordsB.has(w)) intersection++;
27
+ }
28
+ const union = new Set([...wordsA, ...wordsB]).size;
29
+ return intersection / union;
30
+ }
31
+
32
+ /** Similarity above which any two task descriptions are considered duplicates */
33
+ const HIGH_SIMILARITY_THRESHOLD = 0.8;
34
+ /** Lower threshold used when the tasks also target the same agent */
35
+ const SAME_AGENT_SIMILARITY_THRESHOLD = 0.6;
36
+
37
+ export interface DedupMatch {
38
+ task: AgentTask;
39
+ reason: string;
40
+ }
41
+
42
+ /**
43
+ * Check for duplicate tasks created recently.
44
+ * Returns the first matching duplicate, or null if none found.
45
+ */
46
+ export function findDuplicateTask(opts: {
47
+ taskDescription: string;
48
+ creatorAgentId: string;
49
+ targetAgentId?: string;
50
+ slackChannelId?: string;
51
+ slackThreadTs?: string;
52
+ windowMinutes?: number;
53
+ }): DedupMatch | null {
54
+ const recentTasks = findRecentSimilarTasks({
55
+ creatorAgentId: opts.creatorAgentId,
56
+ windowMinutes: opts.windowMinutes ?? 10,
57
+ });
58
+
59
+ for (const existing of recentTasks) {
60
+ // 1. Exact Slack thread match — definitely a duplicate
61
+ if (
62
+ opts.slackChannelId &&
63
+ opts.slackThreadTs &&
64
+ existing.slackChannelId === opts.slackChannelId &&
65
+ existing.slackThreadTs === opts.slackThreadTs
66
+ ) {
67
+ return {
68
+ task: existing,
69
+ reason: `same Slack thread (${opts.slackChannelId}/${opts.slackThreadTs})`,
70
+ };
71
+ }
72
+
73
+ const similarity = jaccardSimilarity(existing.task, opts.taskDescription);
74
+
75
+ // 2. Very similar task description — likely duplicate regardless of target
76
+ if (similarity > HIGH_SIMILARITY_THRESHOLD) {
77
+ return {
78
+ task: existing,
79
+ reason: `similar task description (${(similarity * 100).toFixed(0)}% match)`,
80
+ };
81
+ }
82
+
83
+ // 3. Same target agent + moderately similar task — lower threshold
84
+ if (
85
+ opts.targetAgentId &&
86
+ existing.agentId === opts.targetAgentId &&
87
+ similarity > SAME_AGENT_SIMILARITY_THRESHOLD
88
+ ) {
89
+ return {
90
+ task: existing,
91
+ reason: `similar task to same agent (${(similarity * 100).toFixed(0)}% match)`,
92
+ };
93
+ }
94
+ }
95
+
96
+ return null;
97
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Task lifecycle prompt template definitions (store-progress follow-ups).
3
+ *
4
+ * Each template is registered at module load time via registerTemplate().
5
+ * Handlers import this module for the side-effect of registration.
6
+ */
7
+
8
+ import { registerTemplate } from "../prompts/registry";
9
+
10
+ // ============================================================================
11
+ // Worker task follow-ups (created by store-progress for the lead)
12
+ // ============================================================================
13
+
14
+ registerTemplate({
15
+ eventType: "task.worker.completed",
16
+ header: "",
17
+ defaultBody: `Worker task completed \u2014 review needed.
18
+
19
+ Agent: {{agent_name}}
20
+ Task: "{{task_desc}}"
21
+
22
+ Output:
23
+ {{output_summary}}
24
+
25
+ Use \`get-task-details\` with taskId "{{task_id}}" for full details.`,
26
+ variables: [
27
+ { name: "agent_name", description: "Worker agent name or ID prefix" },
28
+ { name: "task_desc", description: "Task description (truncated to 200 chars)" },
29
+ { name: "output_summary", description: "Task output (truncated to 500 chars)" },
30
+ { name: "task_id", description: "Original task ID" },
31
+ ],
32
+ category: "task_lifecycle",
33
+ });
34
+
35
+ registerTemplate({
36
+ eventType: "task.worker.failed",
37
+ header: "",
38
+ defaultBody: `Worker task failed \u2014 action needed.
39
+
40
+ Agent: {{agent_name}}
41
+ Task: "{{task_desc}}"
42
+
43
+ Failure reason: {{failure_reason}}
44
+
45
+ Decide whether to reassign, retry, or handle the failure. Use \`get-task-details\` with taskId "{{task_id}}" for full details.`,
46
+ variables: [
47
+ { name: "agent_name", description: "Worker agent name or ID prefix" },
48
+ { name: "task_desc", description: "Task description (truncated to 200 chars)" },
49
+ { name: "failure_reason", description: "Failure reason text" },
50
+ { name: "task_id", description: "Original task ID" },
51
+ ],
52
+ category: "task_lifecycle",
53
+ });