@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
@@ -1,934 +0,0 @@
1
- # Runner-Level Polling Implementation Plan
2
-
3
- ## Overview
4
-
5
- Move task polling from inside Claude (MCP tool consuming tokens) to the runner level (TypeScript), so agents are only spawned when there's actual work to do. This reduces token consumption, improves reliability, and enables external event-driven spawning.
6
-
7
- ## Current State Analysis
8
-
9
- ### How It Works Now
10
-
11
- 1. **Runner** (`src/commands/runner.ts:208`): Infinite `while(true)` loop that spawns Claude immediately on each iteration
12
- 2. **Claude**: Receives `/start-worker` or `/start-leader` prompt, then uses `poll-task` MCP tool to wait for tasks
13
- 3. **poll-task** (`src/tools/poll-task.ts`): Polls database every 2 seconds for up to 1 minute, consuming Claude tokens the entire time
14
- 4. **Registration**: Happens inside Claude via `join-swarm` MCP tool
15
-
16
- ### Problems
17
-
18
- - **Token consumption**: Every poll iteration consumes Claude tokens
19
- - **Unreliability**: Claude decides when/how to poll, may miss tasks or poll inefficiently
20
- - **No external control**: Can't trigger Claude spawn from outside events (Slack, webhooks, etc.)
21
- - **Session persistence**: Claude session stays alive during polling, consuming resources
22
-
23
- ### Key Discoveries
24
-
25
- - Runner spawns Claude via `Bun.spawn()` at `src/commands/runner.ts:85`
26
- - Runner options defined at `src/commands/runner.ts:40-47`
27
- - CLI parsing at `src/cli.tsx:38-101` handles flags like `--yolo`, `--system-prompt`
28
- - HTTP API at `src/http.ts` already has `/me`, `/ping`, `/close` endpoints
29
- - Database functions at `src/be/db.ts` have all needed queries (`getOfferedTasksForAgent`, `getPendingTaskForAgent`, `getUnassignedTasksCount`)
30
-
31
- ## Desired End State
32
-
33
- After this implementation:
34
-
35
- 1. **Runner polls via HTTP API** before spawning Claude
36
- 2. **Claude is only spawned** when there's a trigger (task, mention, etc.)
37
- 3. **`--ai-loop` flag** enables the old behavior for backwards compatibility
38
- 4. **New API endpoints** support agent registration and trigger polling from the runner
39
- 5. **Agents register at runner level** before polling begins
40
-
41
- ### Verification
42
-
43
- - `bun run worker` without `--ai-loop` should poll via HTTP and only spawn Claude when work arrives
44
- - `bun run worker --ai-loop` should behave like the current implementation
45
- - `GET /api/poll` should return triggers when tasks/mentions exist
46
- - `POST /api/agents` should register a new agent
47
-
48
- ## What We're NOT Doing
49
-
50
- - **Slack thread subscription changes**: This requires Slack API changes (out of scope)
51
- - **Session persistence across spawns**: Each spawn will be a new Claude session (as designed)
52
- - **Removing poll-task MCP tool**: It remains available for AI-loop mode and manual use
53
- - **Lead-specific trigger types**: Same polling mechanism for both roles initially
54
-
55
- ## Implementation Approach
56
-
57
- We'll implement this in four phases:
58
-
59
- 1. **Phase 1**: Add HTTP API endpoints for agent registration and trigger polling
60
- 2. **Phase 2**: Add `/review-offered-task` plugin command
61
- 3. **Phase 3**: Update runner to poll via API and spawn Claude on-demand
62
- 4. **Phase 4**: Update CLI and add `--ai-loop` flag for backwards compatibility
63
-
64
- ## Phase 1: HTTP API Endpoints
65
-
66
- ### Overview
67
-
68
- Add two new HTTP API endpoints to enable runner-level polling.
69
-
70
- **Important**: Both endpoints use database transactions (`getDb().transaction()`) to ensure:
71
- - **Atomicity**: Check-and-create/update operations complete as a single unit
72
- - **Consistency**: Multiple reads (e.g., checking offered tasks, then pending tasks) see a consistent database state
73
- - **Isolation**: Concurrent requests don't interfere with each other (e.g., two agents trying to claim the same task)
74
-
75
- ### Changes Required
76
-
77
- #### 1. Add Agent Registration Endpoint
78
-
79
- **File**: `src/http.ts`
80
- **Location**: After line 210 (after `/close` endpoint)
81
-
82
- Add `POST /api/agents` endpoint for runner-level agent registration:
83
-
84
- ```typescript
85
- // POST /api/agents - Register a new agent (or return existing if already registered)
86
- if (
87
- req.method === "POST" &&
88
- pathSegments[0] === "api" &&
89
- pathSegments[1] === "agents" &&
90
- !pathSegments[2]
91
- ) {
92
- // Parse request body
93
- const chunks: Buffer[] = [];
94
- for await (const chunk of req) {
95
- chunks.push(chunk);
96
- }
97
- const body = JSON.parse(Buffer.concat(chunks).toString());
98
-
99
- // Validate required fields
100
- if (!body.name || typeof body.name !== "string") {
101
- res.writeHead(400, { "Content-Type": "application/json" });
102
- res.end(JSON.stringify({ error: "Missing or invalid 'name' field" }));
103
- return;
104
- }
105
-
106
- // Use X-Agent-ID header if provided, otherwise generate new UUID
107
- const agentId = myAgentId || crypto.randomUUID();
108
-
109
- // Use transaction to ensure atomicity of check-and-create/update
110
- const result = getDb().transaction(() => {
111
- // Check if agent already exists
112
- const existingAgent = getAgentById(agentId);
113
- if (existingAgent) {
114
- // Update status to idle if offline
115
- if (existingAgent.status === "offline") {
116
- updateAgentStatus(existingAgent.id, "idle");
117
- }
118
- return { agent: getAgentById(agentId), created: false };
119
- }
120
-
121
- // Create new agent
122
- const agent = createAgent({
123
- id: agentId,
124
- name: body.name,
125
- isLead: body.isLead ?? false,
126
- status: "idle",
127
- description: body.description,
128
- role: body.role,
129
- capabilities: body.capabilities,
130
- });
131
-
132
- return { agent, created: true };
133
- })();
134
-
135
- res.writeHead(result.created ? 201 : 200, { "Content-Type": "application/json" });
136
- res.end(JSON.stringify(result.agent));
137
- return;
138
- }
139
- ```
140
-
141
- **Required import**: Add `createAgent` to imports from `./be/db`
142
-
143
- #### 2. Add Trigger Polling Endpoint
144
-
145
- **File**: `src/http.ts`
146
- **Location**: After the agent registration endpoint
147
-
148
- Add `GET /api/poll` endpoint for runner-level trigger polling:
149
-
150
- ```typescript
151
- // GET /api/poll - Poll for triggers (tasks, mentions, etc.)
152
- if (req.method === "GET" && pathSegments[0] === "api" && pathSegments[1] === "poll") {
153
- if (!myAgentId) {
154
- res.writeHead(400, { "Content-Type": "application/json" });
155
- res.end(JSON.stringify({ error: "Missing X-Agent-ID header" }));
156
- return;
157
- }
158
-
159
- // Use transaction for consistent reads across all trigger checks
160
- const result = getDb().transaction(() => {
161
- const agent = getAgentById(myAgentId);
162
- if (!agent) {
163
- return { error: "Agent not found", status: 404 };
164
- }
165
-
166
- // Check for offered tasks first (highest priority)
167
- const offeredTasks = getOfferedTasksForAgent(myAgentId);
168
- if (offeredTasks.length > 0) {
169
- return {
170
- trigger: {
171
- type: "task_offered",
172
- taskId: offeredTasks[0].id,
173
- task: offeredTasks[0],
174
- },
175
- };
176
- }
177
-
178
- // Check for pending tasks (assigned directly to this agent)
179
- const pendingTask = getPendingTaskForAgent(myAgentId);
180
- if (pendingTask) {
181
- return {
182
- trigger: {
183
- type: "task_assigned",
184
- taskId: pendingTask.id,
185
- task: pendingTask,
186
- },
187
- };
188
- }
189
-
190
- // For lead agents, check for unread mentions
191
- if (agent.isLead) {
192
- const inbox = getInboxSummary(myAgentId);
193
- if (inbox.mentionsCount > 0) {
194
- return {
195
- trigger: {
196
- type: "unread_mentions",
197
- mentionsCount: inbox.mentionsCount,
198
- },
199
- };
200
- }
201
-
202
- // Check for tasks needing assignment (unassigned tasks in pool)
203
- const unassignedCount = getUnassignedTasksCount();
204
- if (unassignedCount > 0) {
205
- return {
206
- trigger: {
207
- type: "pool_tasks_available",
208
- count: unassignedCount,
209
- },
210
- };
211
- }
212
- }
213
-
214
- // No trigger found
215
- return { trigger: null };
216
- })();
217
-
218
- // Handle error case
219
- if ("error" in result) {
220
- res.writeHead(result.status, { "Content-Type": "application/json" });
221
- res.end(JSON.stringify({ error: result.error }));
222
- return;
223
- }
224
-
225
- res.writeHead(200, { "Content-Type": "application/json" });
226
- res.end(JSON.stringify(result));
227
- return;
228
- }
229
- ```
230
-
231
- **Required imports**: Add `getOfferedTasksForAgent`, `getPendingTaskForAgent`, `getUnassignedTasksCount` to imports from `./be/db`
232
-
233
- ### Success Criteria
234
-
235
- #### Automated Verification:
236
- - [x] TypeScript compiles without errors: `bun run tsc:check`
237
- - [x] API returns 400 when X-Agent-ID missing for `/api/poll`
238
- - [x] API returns 404 when agent doesn't exist
239
- - [x] API returns trigger when offered task exists
240
- - [x] API returns trigger when pending task exists
241
- - [x] API returns `{ trigger: null }` when no work available
242
-
243
- #### Manual Verification:
244
- - [ ] Test with curl: `curl -X POST http://localhost:3013/api/agents -H "Content-Type: application/json" -H "X-Agent-ID: test-123" -d '{"name": "test-agent"}'`
245
- - [ ] Test poll: `curl http://localhost:3013/api/poll -H "X-Agent-ID: test-123"`
246
-
247
- **Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to Phase 2.
248
-
249
- ---
250
-
251
- ## Phase 2: Review Offered Task Command
252
-
253
- ### Overview
254
-
255
- Add a new plugin command `/review-offered-task` that guides agents through the process of reviewing and accepting/rejecting offered tasks.
256
-
257
- ### Changes Required
258
-
259
- #### 1. Create Plugin Command
260
-
261
- **File**: `plugin/commands/review-offered-task.md` (NEW)
262
-
263
- ```markdown
264
- ---
265
- description: Review a task that has been offered to you and decide whether to accept or reject it
266
- argument-hint: [taskId]
267
- ---
268
-
269
- # Review Offered Task
270
-
271
- You have been offered a task. Your job is to review it and decide whether to accept or reject it based on your capabilities and current workload.
272
-
273
- ## Workflow
274
-
275
- 1. **Get task details**: Call the `get-task-details` tool with the provided `taskId` to understand what the task involves.
276
-
277
- 2. **Evaluate the task**: Consider:
278
- - Does this task match your capabilities?
279
- - Do you have the necessary context or access to complete it?
280
- - Is the task description clear enough to proceed?
281
-
282
- 3. **Make a decision**:
283
- - **Accept**: If you can complete this task, call `task-action` with `action: "accept"` and `taskId: "<taskId>"`. Then immediately use `/work-on-task <taskId>` to start working on it.
284
- - **Reject**: If you cannot complete this task, call `task-action` with `action: "reject"`, `taskId: "<taskId>"`, and provide a `reason` explaining why you're rejecting it (e.g., "Task requires Python expertise which I don't have", "Task description is too vague").
285
-
286
- ## Example Accept Flow
287
-
288
- \`\`\`
289
- 1. get-task-details taskId="abc-123"
290
- 2. [Review the task details]
291
- 3. task-action action="accept" taskId="abc-123"
292
- 4. /work-on-task abc-123
293
- \`\`\`
294
-
295
- ## Example Reject Flow
296
-
297
- \`\`\`
298
- 1. get-task-details taskId="abc-123"
299
- 2. [Review the task details]
300
- 3. task-action action="reject" taskId="abc-123" reason="Task requires access to production database which I don't have"
301
- 4. Reply "DONE" to end the session
302
- \`\`\`
303
-
304
- ## Important Notes
305
-
306
- - Always provide a clear reason when rejecting a task - this helps the lead agent reassign it appropriately
307
- - If you accept, you must immediately start working on the task using `/work-on-task`
308
- - If you reject, the task returns to the unassigned pool for reassignment
309
- ```
310
-
311
- ### Success Criteria
312
-
313
- #### Automated Verification:
314
- - [x] File exists at `plugin/commands/review-offered-task.md`
315
- - [x] File has valid YAML frontmatter with `description` and `argument-hint`
316
-
317
- #### Manual Verification:
318
- - [ ] Command appears in Claude's available commands when running with the plugin
319
- - [ ] Running `/review-offered-task <id>` provides clear guidance
320
-
321
- **Implementation Note**: After completing this phase, pause here for manual confirmation before proceeding to Phase 3.
322
-
323
- ---
324
-
325
- ## Phase 3: Runner-Level Polling
326
-
327
- ### Overview
328
-
329
- Update the runner to poll via HTTP API before spawning Claude, and only spawn when there's a trigger.
330
-
331
- ### Changes Required
332
-
333
- #### 1. Add Trigger Types
334
-
335
- **File**: `src/commands/runner.ts`
336
- **Location**: After line 55 (after `RunClaudeIterationOptions` interface)
337
-
338
- ```typescript
339
- /** Trigger types returned by the poll API */
340
- interface Trigger {
341
- type: "task_assigned" | "task_offered" | "unread_mentions" | "pool_tasks_available";
342
- taskId?: string;
343
- task?: unknown;
344
- mentionsCount?: number;
345
- count?: number;
346
- }
347
-
348
- /** Options for polling */
349
- interface PollOptions {
350
- swarmUrl: string;
351
- apiKey: string;
352
- agentId: string;
353
- pollInterval: number;
354
- pollTimeout: number;
355
- }
356
- ```
357
-
358
- #### 2. Add Registration Function
359
-
360
- **File**: `src/commands/runner.ts`
361
- **Location**: After the new interfaces
362
-
363
- ```typescript
364
- /** Register agent via HTTP API */
365
- async function registerAgent(opts: {
366
- swarmUrl: string;
367
- apiKey: string;
368
- agentId: string;
369
- name: string;
370
- isLead: boolean;
371
- capabilities?: string[];
372
- }): Promise<void> {
373
- const headers: Record<string, string> = {
374
- "Content-Type": "application/json",
375
- "X-Agent-ID": opts.agentId,
376
- };
377
- if (opts.apiKey) {
378
- headers["Authorization"] = `Bearer ${opts.apiKey}`;
379
- }
380
-
381
- const response = await fetch(`${opts.swarmUrl}/api/agents`, {
382
- method: "POST",
383
- headers,
384
- body: JSON.stringify({
385
- name: opts.name,
386
- isLead: opts.isLead,
387
- capabilities: opts.capabilities,
388
- }),
389
- });
390
-
391
- if (!response.ok) {
392
- const error = await response.text();
393
- throw new Error(`Failed to register agent: ${response.status} ${error}`);
394
- }
395
- }
396
- ```
397
-
398
- #### 3. Add Poll Function
399
-
400
- **File**: `src/commands/runner.ts`
401
- **Location**: After `registerAgent` function
402
-
403
- ```typescript
404
- /** Poll for triggers via HTTP API */
405
- async function pollForTrigger(opts: PollOptions): Promise<Trigger | null> {
406
- const startTime = Date.now();
407
- const headers: Record<string, string> = {
408
- "X-Agent-ID": opts.agentId,
409
- };
410
- if (opts.apiKey) {
411
- headers["Authorization"] = `Bearer ${opts.apiKey}`;
412
- }
413
-
414
- while (Date.now() - startTime < opts.pollTimeout) {
415
- try {
416
- const response = await fetch(`${opts.swarmUrl}/api/poll`, {
417
- method: "GET",
418
- headers,
419
- });
420
-
421
- if (!response.ok) {
422
- console.warn(`[runner] Poll request failed: ${response.status}`);
423
- await Bun.sleep(opts.pollInterval);
424
- continue;
425
- }
426
-
427
- const data = (await response.json()) as { trigger: Trigger | null };
428
- if (data.trigger) {
429
- return data.trigger;
430
- }
431
- } catch (error) {
432
- console.warn(`[runner] Poll request error: ${error}`);
433
- }
434
-
435
- await Bun.sleep(opts.pollInterval);
436
- }
437
-
438
- return null; // Timeout reached, no trigger found
439
- }
440
- ```
441
-
442
- #### 4. Add Prompt Builder Function
443
-
444
- **File**: `src/commands/runner.ts`
445
- **Location**: After `pollForTrigger` function
446
-
447
- ```typescript
448
- /** Build prompt based on trigger type */
449
- function buildPromptForTrigger(trigger: Trigger, defaultPrompt: string): string {
450
- switch (trigger.type) {
451
- case "task_assigned":
452
- // Use the work-on-task command with task ID
453
- return `/work-on-task ${trigger.taskId}`;
454
-
455
- case "task_offered":
456
- // Use the review-offered-task command to accept/reject
457
- return `/review-offered-task ${trigger.taskId}`;
458
-
459
- case "unread_mentions":
460
- // Check messages
461
- return "/swarm-chat";
462
-
463
- case "pool_tasks_available":
464
- // Let lead review and assign tasks
465
- return defaultPrompt;
466
-
467
- default:
468
- return defaultPrompt;
469
- }
470
- }
471
- ```
472
-
473
- #### 5. Update RunnerOptions Interface
474
-
475
- **File**: `src/commands/runner.ts`
476
- **Location**: Line 40-47 (update existing interface)
477
-
478
- ```typescript
479
- export interface RunnerOptions {
480
- prompt?: string;
481
- yolo?: boolean;
482
- systemPrompt?: string;
483
- systemPromptFile?: string;
484
- logsDir?: string;
485
- additionalArgs?: string[];
486
- aiLoop?: boolean; // NEW: Use AI-based loop (old behavior)
487
- }
488
- ```
489
-
490
- #### 6. Update runAgent Function
491
-
492
- **File**: `src/commands/runner.ts`
493
- **Location**: Update the `runAgent` function (lines 138-258)
494
-
495
- Replace the while loop section (lines 206-257) with:
496
-
497
- ```typescript
498
- const isAiLoop = opts.aiLoop || process.env.AI_LOOP === "true";
499
- const apiKey = process.env.API_KEY || "";
500
-
501
- // Constants for polling
502
- const POLL_INTERVAL_MS = 2000; // 2 seconds between polls
503
- const POLL_TIMEOUT_MS = 60000; // 1 minute timeout before retrying
504
-
505
- let iteration = 0;
506
-
507
- if (!isAiLoop) {
508
- // NEW: Runner-level polling mode
509
- console.log(`[${role}] Mode: runner-level polling (use --ai-loop for AI-based polling)`);
510
-
511
- // Register agent before starting
512
- const agentName = process.env.AGENT_NAME || `${role}-${agentId.slice(0, 8)}`;
513
- try {
514
- await registerAgent({
515
- swarmUrl,
516
- apiKey,
517
- agentId,
518
- name: agentName,
519
- isLead: role === "lead",
520
- capabilities: config.capabilities,
521
- });
522
- console.log(`[${role}] Registered as "${agentName}" (ID: ${agentId})`);
523
- } catch (error) {
524
- console.error(`[${role}] Failed to register: ${error}`);
525
- process.exit(1);
526
- }
527
-
528
- while (true) {
529
- console.log(`\n[${role}] Polling for triggers...`);
530
-
531
- const trigger = await pollForTrigger({
532
- swarmUrl,
533
- apiKey,
534
- agentId,
535
- pollInterval: POLL_INTERVAL_MS,
536
- pollTimeout: POLL_TIMEOUT_MS,
537
- });
538
-
539
- if (!trigger) {
540
- console.log(`[${role}] No trigger found, polling again...`);
541
- continue;
542
- }
543
-
544
- console.log(`[${role}] Trigger received: ${trigger.type}`);
545
-
546
- // Build prompt based on trigger
547
- const triggerPrompt = buildPromptForTrigger(trigger, prompt);
548
-
549
- iteration++;
550
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
551
- const logFile = `${logDir}/${timestamp}.jsonl`;
552
-
553
- console.log(`\n[${role}] === Iteration ${iteration} ===`);
554
- console.log(`[${role}] Logging to: ${logFile}`);
555
- console.log(`[${role}] Prompt: ${triggerPrompt}`);
556
-
557
- const metadata = {
558
- type: metadataType,
559
- sessionId,
560
- iteration,
561
- timestamp: new Date().toISOString(),
562
- prompt: triggerPrompt,
563
- trigger: trigger.type,
564
- yolo: isYolo,
565
- };
566
- await Bun.write(logFile, `${JSON.stringify(metadata)}\n`);
567
-
568
- const exitCode = await runClaudeIteration({
569
- prompt: triggerPrompt,
570
- logFile,
571
- systemPrompt: resolvedSystemPrompt,
572
- additionalArgs: opts.additionalArgs,
573
- role,
574
- });
575
-
576
- if (exitCode !== 0) {
577
- const errorLog = {
578
- timestamp: new Date().toISOString(),
579
- iteration,
580
- exitCode,
581
- trigger: trigger.type,
582
- error: true,
583
- };
584
-
585
- const errorsFile = `${logDir}/errors.jsonl`;
586
- const errorsFileRef = Bun.file(errorsFile);
587
- const existingErrors = (await errorsFileRef.exists()) ? await errorsFileRef.text() : "";
588
- await Bun.write(errorsFile, `${existingErrors}${JSON.stringify(errorLog)}\n`);
589
-
590
- if (!isYolo) {
591
- console.error(`[${role}] Claude exited with code ${exitCode}. Stopping.`);
592
- console.error(`[${role}] Error logged to: ${errorsFile}`);
593
- process.exit(exitCode);
594
- }
595
-
596
- console.warn(`[${role}] Claude exited with code ${exitCode}. YOLO mode - continuing...`);
597
- }
598
-
599
- console.log(`[${role}] Iteration ${iteration} complete. Polling for next trigger...`);
600
- }
601
- } else {
602
- // Original AI-loop mode (existing behavior)
603
- console.log(`[${role}] Mode: AI-based polling (legacy)`);
604
-
605
- while (true) {
606
- iteration++;
607
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
608
- const logFile = `${logDir}/${timestamp}.jsonl`;
609
-
610
- console.log(`\n[${role}] === Iteration ${iteration} ===`);
611
- console.log(`[${role}] Logging to: ${logFile}`);
612
-
613
- const metadata = {
614
- type: metadataType,
615
- sessionId,
616
- iteration,
617
- timestamp: new Date().toISOString(),
618
- prompt,
619
- yolo: isYolo,
620
- };
621
- await Bun.write(logFile, `${JSON.stringify(metadata)}\n`);
622
-
623
- const exitCode = await runClaudeIteration({
624
- prompt,
625
- logFile,
626
- systemPrompt: resolvedSystemPrompt,
627
- additionalArgs: opts.additionalArgs,
628
- role,
629
- });
630
-
631
- if (exitCode !== 0) {
632
- const errorLog = {
633
- timestamp: new Date().toISOString(),
634
- iteration,
635
- exitCode,
636
- error: true,
637
- };
638
-
639
- const errorsFile = `${logDir}/errors.jsonl`;
640
- const errorsFileRef = Bun.file(errorsFile);
641
- const existingErrors = (await errorsFileRef.exists()) ? await errorsFileRef.text() : "";
642
- await Bun.write(errorsFile, `${existingErrors}${JSON.stringify(errorLog)}\n`);
643
-
644
- if (!isYolo) {
645
- console.error(`[${role}] Claude exited with code ${exitCode}. Stopping.`);
646
- console.error(`[${role}] Error logged to: ${errorsFile}`);
647
- process.exit(exitCode);
648
- }
649
-
650
- console.warn(`[${role}] Claude exited with code ${exitCode}. YOLO mode - continuing...`);
651
- }
652
-
653
- console.log(`[${role}] Iteration ${iteration} complete. Starting next iteration...`);
654
- }
655
- }
656
- ```
657
-
658
- ### Success Criteria
659
-
660
- #### Automated Verification:
661
- - [x] TypeScript compiles without errors: `bun run tsc:check`
662
- - [x] Runner starts without `--ai-loop` and logs "runner-level polling"
663
- - [x] Runner with `--ai-loop` logs "AI-based polling (legacy)"
664
-
665
- #### Manual Verification:
666
- - [ ] Start MCP server: `bun run mcp`
667
- - [ ] In another terminal, start worker: `AGENT_ID=test-worker SWARM_URL=http://localhost:3013 bun run worker`
668
- - [ ] Verify worker polls and waits (no Claude spawned)
669
- - [ ] Create a task via API and verify Claude is spawned
670
- - [ ] Test `--ai-loop` flag works as before
671
-
672
- **Implementation Note**: After completing this phase and all automated verification passes, pause here for manual confirmation before proceeding to Phase 4.
673
-
674
- ---
675
-
676
- ## Phase 4: CLI Flag and Final Integration
677
-
678
- ### Overview
679
-
680
- Add the `--ai-loop` CLI flag and update documentation.
681
-
682
- ### Changes Required
683
-
684
- #### 1. Update CLI Argument Parsing
685
-
686
- **File**: `src/cli.tsx`
687
- **Location**: Line 32 (add to ParsedArgs interface)
688
-
689
- ```typescript
690
- interface ParsedArgs {
691
- command: string | undefined;
692
- port: string;
693
- key: string;
694
- msg: string;
695
- headless: boolean;
696
- dryRun: boolean;
697
- restore: boolean;
698
- yes: boolean;
699
- yolo: boolean;
700
- systemPrompt: string;
701
- systemPromptFile: string;
702
- additionalArgs: string[];
703
- aiLoop: boolean; // NEW
704
- }
705
- ```
706
-
707
- **Location**: Line 47 (add to defaults in parseArgs)
708
-
709
- ```typescript
710
- let aiLoop = false;
711
- ```
712
-
713
- **Location**: After line 83 (add flag handling in parseArgs)
714
-
715
- ```typescript
716
- } else if (arg === "--ai-loop") {
717
- aiLoop = true;
718
- }
719
- ```
720
-
721
- **Location**: Line 99 (add to return object)
722
-
723
- ```typescript
724
- return {
725
- command,
726
- port,
727
- key,
728
- msg,
729
- headless,
730
- dryRun,
731
- restore,
732
- yes,
733
- yolo,
734
- systemPrompt,
735
- systemPromptFile,
736
- additionalArgs,
737
- aiLoop, // NEW
738
- };
739
- ```
740
-
741
- #### 2. Update WorkerRunner and LeadRunner Components
742
-
743
- **File**: `src/cli.tsx`
744
- **Location**: Line 432 (update RunnerProps interface)
745
-
746
- ```typescript
747
- interface RunnerProps {
748
- prompt: string;
749
- yolo: boolean;
750
- systemPrompt: string;
751
- systemPromptFile: string;
752
- additionalArgs: string[];
753
- aiLoop: boolean; // NEW
754
- }
755
- ```
756
-
757
- **Location**: Lines 440-465 (update WorkerRunner)
758
-
759
- Add `aiLoop` to the destructured props and pass it to `runWorker`:
760
-
761
- ```typescript
762
- function WorkerRunner({
763
- prompt,
764
- yolo,
765
- systemPrompt,
766
- systemPromptFile,
767
- additionalArgs,
768
- aiLoop, // NEW
769
- }: RunnerProps) {
770
- const { exit } = useApp();
771
-
772
- useEffect(() => {
773
- runWorker({
774
- prompt: prompt || undefined,
775
- yolo,
776
- systemPrompt: systemPrompt || undefined,
777
- systemPromptFile: systemPromptFile || undefined,
778
- additionalArgs,
779
- logsDir: "./logs",
780
- aiLoop, // NEW
781
- }).catch((err) => {
782
- console.error("[error] Worker encountered an error:", err);
783
- exit(err);
784
- });
785
- }, [prompt, yolo, systemPrompt, systemPromptFile, additionalArgs, aiLoop, exit]);
786
-
787
- return null;
788
- }
789
- ```
790
-
791
- **Location**: Lines 467-486 (update LeadRunner similarly)
792
-
793
- #### 3. Update Switch Statement
794
-
795
- **File**: `src/cli.tsx`
796
- **Location**: Lines 540-559 (update worker and lead cases)
797
-
798
- ```typescript
799
- case "worker":
800
- return (
801
- <WorkerRunner
802
- prompt={msg}
803
- yolo={yolo}
804
- systemPrompt={systemPrompt}
805
- systemPromptFile={systemPromptFile}
806
- additionalArgs={additionalArgs}
807
- aiLoop={aiLoop} // NEW
808
- />
809
- );
810
- case "lead":
811
- return (
812
- <LeadRunner
813
- prompt={msg}
814
- yolo={yolo}
815
- systemPrompt={systemPrompt}
816
- systemPromptFile={systemPromptFile}
817
- additionalArgs={additionalArgs}
818
- aiLoop={aiLoop} // NEW
819
- />
820
- );
821
- ```
822
-
823
- #### 4. Update Help Text
824
-
825
- **File**: `src/cli.tsx`
826
- **Location**: After line 255 (add --ai-loop to worker/lead options)
827
-
828
- ```tsx
829
- <Box>
830
- <Box width={30}>
831
- <Text color="yellow">--ai-loop</Text>
832
- </Box>
833
- <Text>Use AI-based polling (legacy mode)</Text>
834
- </Box>
835
- ```
836
-
837
- #### 5. Update Environment Variable Documentation
838
-
839
- **File**: `src/cli.tsx`
840
- **Location**: After line 336 (add AI_LOOP env var)
841
-
842
- ```tsx
843
- <Box>
844
- <Box width={24}>
845
- <Text color="magenta">AI_LOOP</Text>
846
- </Box>
847
- <Text>If "true", use AI-based polling</Text>
848
- </Box>
849
- ```
850
-
851
- ### Success Criteria
852
-
853
- #### Automated Verification:
854
- - [x] TypeScript compiles without errors: `bun run tsc:check`
855
- - [x] Linting passes: `bun run lint`
856
- - [x] `bun run worker --help` shows `--ai-loop` option
857
-
858
- #### Manual Verification:
859
- - [ ] `bun run worker` defaults to runner-level polling
860
- - [ ] `bun run worker --ai-loop` uses AI-based polling
861
- - [ ] `AI_LOOP=true bun run worker` uses AI-based polling
862
- - [ ] `bun run lead` defaults to runner-level polling
863
- - [ ] `bun run lead --ai-loop` uses AI-based polling
864
-
865
- ---
866
-
867
- ## Testing Strategy
868
-
869
- ### Unit Tests
870
-
871
- No new unit tests required - this is primarily integration behavior.
872
-
873
- ### Integration Tests
874
-
875
- Create a test script to verify the polling mechanism:
876
-
877
- ```bash
878
- #!/bin/bash
879
- # test-runner-polling.sh
880
-
881
- # Start MCP server in background
882
- bun run mcp &
883
- MCP_PID=$!
884
- sleep 2
885
-
886
- # Start worker with runner-level polling
887
- AGENT_ID=test-worker SWARM_URL=http://localhost:3013 timeout 10 bun run worker &
888
- WORKER_PID=$!
889
- sleep 3
890
-
891
- # Create a task
892
- curl -X POST http://localhost:3013/api/tasks \
893
- -H "Content-Type: application/json" \
894
- -H "X-Agent-ID: lead-agent" \
895
- -d '{"task": "Test task", "agentId": "test-worker"}'
896
-
897
- # Wait for worker to pick up task
898
- sleep 5
899
-
900
- # Cleanup
901
- kill $WORKER_PID $MCP_PID 2>/dev/null
902
- ```
903
-
904
- ### Manual Testing Steps
905
-
906
- 1. Start MCP server: `bun run mcp`
907
- 2. Start worker in new terminal: `AGENT_ID=test-worker SWARM_URL=http://localhost:3013 bun run worker`
908
- 3. Observe: Worker should log "Polling for triggers..." and wait
909
- 4. Create a task via dashboard or API
910
- 5. Observe: Worker should log trigger received and spawn Claude
911
- 6. Test `--ai-loop` mode works as before
912
-
913
- ## Performance Considerations
914
-
915
- - **Reduced token consumption**: Claude only spawned when there's work (major savings)
916
- - **Poll interval**: 2 seconds is reasonable; can be tuned via env var if needed
917
- - **Poll timeout**: 1 minute before retry loop; keeps connections fresh
918
- - **HTTP overhead**: Minimal compared to Claude session costs
919
-
920
- ## Migration Notes
921
-
922
- - **Backwards compatible**: `--ai-loop` flag preserves existing behavior
923
- - **No database changes**: Uses existing tables and queries
924
- - **No breaking changes**: Existing commands work as before
925
-
926
- ## References
927
-
928
- - Related research: `thoughts/shared/research/2025-12-22-runner-loop-architecture.md`
929
- - Runner implementation: `src/commands/runner.ts:138-258`
930
- - HTTP API: `src/http.ts:72-583`
931
- - CLI parsing: `src/cli.tsx:38-101`
932
- - Poll-task MCP tool: `src/tools/poll-task.ts`
933
- - Work-on-task command: `plugin/commands/work-on-task.md`
934
- - Review-offered-task command (NEW): `plugin/commands/review-offered-task.md`