@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,166 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import * as z from "zod";
3
+ import {
4
+ createAgentMailInboxMapping,
5
+ deleteAgentMailInboxMapping,
6
+ getAgentById,
7
+ getAgentMailInboxMapping,
8
+ getAgentMailInboxMappingsByAgent,
9
+ } from "@/be/db";
10
+ import { createToolRegistrar } from "@/tools/utils";
11
+
12
+ export const registerRegisterAgentMailInboxTool = (server: McpServer) => {
13
+ createToolRegistrar(server)(
14
+ "register-agentmail-inbox",
15
+ {
16
+ title: "Register AgentMail Inbox",
17
+ annotations: { idempotentHint: true },
18
+ description:
19
+ "Register an AgentMail inbox ID to route incoming emails to this agent. When emails arrive at this inbox, they will be routed to you as tasks (for workers) or inbox messages (for leads). Use action 'register' to add a mapping, 'unregister' to remove one, or 'list' to see your current mappings.",
20
+ inputSchema: z.object({
21
+ action: z
22
+ .enum(["register", "unregister", "list"])
23
+ .describe("Action to perform: register, unregister, or list inbox mappings."),
24
+ inboxId: z
25
+ .string()
26
+ .optional()
27
+ .describe("The AgentMail inbox ID (e.g., 'inb_xxx'). Required for register/unregister."),
28
+ inboxEmail: z
29
+ .string()
30
+ .optional()
31
+ .describe("Optional email address for this inbox (for reference only)."),
32
+ }),
33
+ outputSchema: z.object({
34
+ yourAgentId: z.string().uuid().optional(),
35
+ success: z.boolean(),
36
+ message: z.string(),
37
+ mappings: z
38
+ .array(
39
+ z.object({
40
+ id: z.string(),
41
+ inboxId: z.string(),
42
+ agentId: z.string(),
43
+ inboxEmail: z.string().nullable(),
44
+ createdAt: z.string(),
45
+ }),
46
+ )
47
+ .optional(),
48
+ }),
49
+ },
50
+ async ({ action, inboxId, inboxEmail }, requestInfo, _meta) => {
51
+ if (!requestInfo.agentId) {
52
+ return {
53
+ content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
54
+ structuredContent: {
55
+ success: false,
56
+ message: 'Agent ID not found. Set the "X-Agent-ID" header.',
57
+ },
58
+ };
59
+ }
60
+
61
+ try {
62
+ const agent = getAgentById(requestInfo.agentId);
63
+ if (!agent) {
64
+ return {
65
+ content: [{ type: "text", text: "Agent not found." }],
66
+ structuredContent: {
67
+ yourAgentId: requestInfo.agentId,
68
+ success: false,
69
+ message: "Agent not found.",
70
+ },
71
+ };
72
+ }
73
+
74
+ if (action === "list") {
75
+ const mappings = getAgentMailInboxMappingsByAgent(requestInfo.agentId);
76
+ const text =
77
+ mappings.length === 0
78
+ ? "No AgentMail inbox mappings registered."
79
+ : `Found ${mappings.length} mapping(s):\n${mappings.map((m) => ` - ${m.inboxId} (${m.inboxEmail ?? "no email"})`).join("\n")}`;
80
+ return {
81
+ content: [{ type: "text", text }],
82
+ structuredContent: {
83
+ yourAgentId: requestInfo.agentId,
84
+ success: true,
85
+ message: text,
86
+ mappings,
87
+ },
88
+ };
89
+ }
90
+
91
+ if (!inboxId) {
92
+ return {
93
+ content: [{ type: "text", text: "inboxId is required for register/unregister." }],
94
+ structuredContent: {
95
+ yourAgentId: requestInfo.agentId,
96
+ success: false,
97
+ message: "inboxId is required for register/unregister.",
98
+ },
99
+ };
100
+ }
101
+
102
+ if (action === "register") {
103
+ const mapping = createAgentMailInboxMapping(inboxId, requestInfo.agentId, inboxEmail);
104
+ const text = `Registered inbox ${inboxId} → agent ${agent.name} (${requestInfo.agentId})`;
105
+ return {
106
+ content: [{ type: "text", text }],
107
+ structuredContent: {
108
+ yourAgentId: requestInfo.agentId,
109
+ success: true,
110
+ message: text,
111
+ mappings: [mapping],
112
+ },
113
+ };
114
+ }
115
+
116
+ if (action === "unregister") {
117
+ // Check ownership before allowing unregister
118
+ const existing = getAgentMailInboxMapping(inboxId);
119
+ if (existing && existing.agentId !== requestInfo.agentId) {
120
+ const text = `Cannot unregister inbox ${inboxId}: owned by another agent`;
121
+ return {
122
+ content: [{ type: "text", text }],
123
+ structuredContent: {
124
+ yourAgentId: requestInfo.agentId,
125
+ success: false,
126
+ message: text,
127
+ },
128
+ };
129
+ }
130
+
131
+ const deleted = deleteAgentMailInboxMapping(inboxId);
132
+ const text = deleted
133
+ ? `Unregistered inbox ${inboxId}`
134
+ : `No mapping found for inbox ${inboxId}`;
135
+ return {
136
+ content: [{ type: "text", text }],
137
+ structuredContent: {
138
+ yourAgentId: requestInfo.agentId,
139
+ success: deleted,
140
+ message: text,
141
+ },
142
+ };
143
+ }
144
+
145
+ return {
146
+ content: [{ type: "text", text: `Unknown action: ${action}` }],
147
+ structuredContent: {
148
+ yourAgentId: requestInfo.agentId,
149
+ success: false,
150
+ message: `Unknown action: ${action}`,
151
+ },
152
+ };
153
+ } catch (err) {
154
+ const errorMessage = err instanceof Error ? err.message : String(err);
155
+ return {
156
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
157
+ structuredContent: {
158
+ yourAgentId: requestInfo.agentId,
159
+ success: false,
160
+ message: errorMessage,
161
+ },
162
+ };
163
+ }
164
+ },
165
+ );
166
+ };
@@ -13,6 +13,8 @@ export const registerRegisterServiceTool = (server: McpServer) => {
13
13
  title: "Register Service",
14
14
  description:
15
15
  "Register a background service (e.g., PM2 process) for discovery by other agents. The service URL is automatically derived from your agent ID (https://{AGENT_ID}.{SWARM_URL}). Each agent can only run one service on port 3000.",
16
+ annotations: { idempotentHint: true },
17
+
16
18
  inputSchema: z.object({
17
19
  script: z.string().min(1).describe("Path to the script to run (required for PM2 restart)."),
18
20
  description: z.string().optional().describe("What this service does."),
@@ -10,8 +10,9 @@ export const registerCreateScheduleTool = (server: McpServer) => {
10
10
  "create-schedule",
11
11
  {
12
12
  title: "Create Scheduled Task",
13
+ annotations: { destructiveHint: false },
13
14
  description:
14
- "Create a new scheduled task that will automatically create agent tasks at specified intervals. Either cronExpression or intervalMs must be provided.",
15
+ "Create a new scheduled task. For recurring: provide cronExpression or intervalMs. For one-time: provide delayMs or runAt with scheduleType 'one_time'.",
15
16
  inputSchema: z.object({
16
17
  name: z
17
18
  .string()
@@ -22,16 +23,32 @@ export const registerCreateScheduleTool = (server: McpServer) => {
22
23
  .string()
23
24
  .min(1)
24
25
  .describe("The task description that will be created each time"),
26
+ scheduleType: z
27
+ .enum(["recurring", "one_time"])
28
+ .default("recurring")
29
+ .optional()
30
+ .describe("Schedule type: 'recurring' (default) or 'one_time'"),
25
31
  cronExpression: z
26
32
  .string()
27
33
  .optional()
28
- .describe("Cron expression (e.g., '0 9 * * *' for daily at 9 AM)"),
34
+ .describe("Cron expression for recurring schedules (e.g., '0 9 * * *')"),
29
35
  intervalMs: z
30
36
  .number()
31
37
  .int()
32
38
  .positive()
33
39
  .optional()
34
- .describe("Interval in milliseconds (e.g., 3600000 for hourly)"),
40
+ .describe("Interval in milliseconds for recurring schedules (e.g., 3600000 for hourly)"),
41
+ delayMs: z
42
+ .number()
43
+ .int()
44
+ .positive()
45
+ .optional()
46
+ .describe("Delay in milliseconds for one-time schedules (e.g., 1800000 for 30 min)"),
47
+ runAt: z
48
+ .string()
49
+ .datetime()
50
+ .optional()
51
+ .describe("ISO datetime for one-time schedules (e.g., '2026-03-06T15:00:00Z')"),
35
52
  description: z.string().optional().describe("Human-readable description of the schedule"),
36
53
  taskType: z
37
54
  .string()
@@ -58,6 +75,12 @@ export const registerCreateScheduleTool = (server: McpServer) => {
58
75
  .default(true)
59
76
  .optional()
60
77
  .describe("Whether the schedule is enabled (default: true)"),
78
+ model: z
79
+ .enum(["haiku", "sonnet", "opus"])
80
+ .optional()
81
+ .describe(
82
+ "Model to use for tasks created by this schedule ('haiku', 'sonnet', or 'opus'). If not set, uses agent/global config or defaults to 'opus'.",
83
+ ),
61
84
  }),
62
85
  outputSchema: z.object({
63
86
  yourAgentId: z.string().uuid().optional(),
@@ -80,6 +103,8 @@ export const registerCreateScheduleTool = (server: McpServer) => {
80
103
  nextRunAt: z.string().optional(),
81
104
  createdByAgentId: z.string().optional(),
82
105
  timezone: z.string(),
106
+ model: z.string().optional(),
107
+ scheduleType: z.string(),
83
108
  createdAt: z.string(),
84
109
  lastUpdatedAt: z.string(),
85
110
  })
@@ -90,8 +115,11 @@ export const registerCreateScheduleTool = (server: McpServer) => {
90
115
  {
91
116
  name,
92
117
  taskTemplate,
118
+ scheduleType,
93
119
  cronExpression,
94
120
  intervalMs,
121
+ delayMs,
122
+ runAt,
95
123
  description,
96
124
  taskType,
97
125
  tags,
@@ -99,6 +127,7 @@ export const registerCreateScheduleTool = (server: McpServer) => {
99
127
  targetAgentId,
100
128
  timezone,
101
129
  enabled,
130
+ model,
102
131
  },
103
132
  requestInfo,
104
133
  _meta,
@@ -113,17 +142,89 @@ export const registerCreateScheduleTool = (server: McpServer) => {
113
142
  };
114
143
  }
115
144
 
116
- // Validate that either cronExpression or intervalMs is provided
117
- if (!cronExpression && !intervalMs) {
118
- return {
119
- content: [
120
- { type: "text", text: "Either cronExpression or intervalMs must be provided." },
121
- ],
122
- structuredContent: {
123
- success: false,
124
- message: "Either cronExpression or intervalMs must be provided.",
125
- },
126
- };
145
+ const isOneTime = scheduleType === "one_time";
146
+
147
+ // Validate params based on schedule type
148
+ if (isOneTime) {
149
+ if (cronExpression || intervalMs) {
150
+ return {
151
+ content: [
152
+ {
153
+ type: "text",
154
+ text: "One-time schedules cannot use cronExpression or intervalMs. Use delayMs or runAt instead.",
155
+ },
156
+ ],
157
+ structuredContent: {
158
+ success: false,
159
+ message:
160
+ "One-time schedules cannot use cronExpression or intervalMs. Use delayMs or runAt instead.",
161
+ },
162
+ };
163
+ }
164
+ if (!delayMs && !runAt) {
165
+ return {
166
+ content: [
167
+ {
168
+ type: "text",
169
+ text: "One-time schedules require either delayMs or runAt.",
170
+ },
171
+ ],
172
+ structuredContent: {
173
+ success: false,
174
+ message: "One-time schedules require either delayMs or runAt.",
175
+ },
176
+ };
177
+ }
178
+ if (delayMs && runAt) {
179
+ return {
180
+ content: [
181
+ {
182
+ type: "text",
183
+ text: "Provide either delayMs or runAt, not both.",
184
+ },
185
+ ],
186
+ structuredContent: {
187
+ success: false,
188
+ message: "Provide either delayMs or runAt, not both.",
189
+ },
190
+ };
191
+ }
192
+ if (runAt && new Date(runAt).getTime() <= Date.now()) {
193
+ return {
194
+ content: [{ type: "text", text: "runAt must be in the future." }],
195
+ structuredContent: {
196
+ success: false,
197
+ message: "runAt must be in the future.",
198
+ },
199
+ };
200
+ }
201
+ } else {
202
+ if (delayMs || runAt) {
203
+ return {
204
+ content: [
205
+ {
206
+ type: "text",
207
+ text: "delayMs and runAt are only for one-time schedules. Set scheduleType to 'one_time'.",
208
+ },
209
+ ],
210
+ structuredContent: {
211
+ success: false,
212
+ message:
213
+ "delayMs and runAt are only for one-time schedules. Set scheduleType to 'one_time'.",
214
+ },
215
+ };
216
+ }
217
+ if (!cronExpression && !intervalMs) {
218
+ return {
219
+ content: [
220
+ { type: "text", text: "Either cronExpression or intervalMs must be provided." },
221
+ ],
222
+ structuredContent: {
223
+ success: false,
224
+ message: "Either cronExpression or intervalMs must be provided.",
225
+ },
226
+ };
227
+ }
127
228
  }
128
229
 
129
230
  // Validate cron expression syntax
@@ -170,14 +271,19 @@ export const registerCreateScheduleTool = (server: McpServer) => {
170
271
 
171
272
  try {
172
273
  // Calculate initial nextRunAt
173
- const tempSchedule = {
174
- cronExpression,
175
- intervalMs,
176
- timezone: timezone || "UTC",
177
- } as Parameters<typeof calculateNextRun>[0];
178
-
179
- const nextRunAt =
180
- enabled !== false ? calculateNextRun(tempSchedule, new Date()) : undefined;
274
+ let nextRunAt: string | undefined;
275
+ if (enabled === false) {
276
+ nextRunAt = undefined;
277
+ } else if (isOneTime) {
278
+ nextRunAt = delayMs ? new Date(Date.now() + delayMs).toISOString() : runAt!;
279
+ } else {
280
+ const tempSchedule = {
281
+ cronExpression,
282
+ intervalMs,
283
+ timezone: timezone || "UTC",
284
+ } as Parameters<typeof calculateNextRun>[0];
285
+ nextRunAt = calculateNextRun(tempSchedule, new Date());
286
+ }
181
287
 
182
288
  const schedule = createScheduledTask({
183
289
  name,
@@ -193,14 +299,18 @@ export const registerCreateScheduleTool = (server: McpServer) => {
193
299
  enabled,
194
300
  nextRunAt,
195
301
  createdByAgentId: requestInfo.agentId,
302
+ model,
303
+ scheduleType: scheduleType ?? "recurring",
196
304
  });
197
305
 
198
- const scheduleType = cronExpression || `every ${intervalMs}ms`;
306
+ const scheduleDesc = isOneTime
307
+ ? `one-time at ${schedule.nextRunAt}`
308
+ : cronExpression || `every ${intervalMs}ms`;
199
309
  return {
200
310
  content: [
201
311
  {
202
312
  type: "text",
203
- text: `Created schedule "${name}" (${scheduleType}). Next run: ${schedule.nextRunAt || "disabled"}`,
313
+ text: `Created schedule "${name}" (${scheduleDesc}). Next run: ${schedule.nextRunAt || "disabled"}`,
204
314
  },
205
315
  ],
206
316
  structuredContent: {
@@ -15,6 +15,8 @@ export const registerDeleteScheduleTool = (server: McpServer) => {
15
15
  title: "Delete Scheduled Task",
16
16
  description:
17
17
  "Delete a scheduled task permanently. Only the creator or lead agent can delete schedules.",
18
+ annotations: { destructiveHint: true },
19
+
18
20
  inputSchema: z.object({
19
21
  scheduleId: z.string().uuid().optional().describe("Schedule ID to delete"),
20
22
  name: z.string().optional().describe("Schedule name to delete (alternative to ID)"),
@@ -10,9 +10,20 @@ export const registerListSchedulesTool = (server: McpServer) => {
10
10
  title: "List Scheduled Tasks",
11
11
  description:
12
12
  "View all scheduled tasks with optional filters. Use this to discover existing schedules.",
13
+ annotations: { readOnlyHint: true },
14
+
13
15
  inputSchema: z.object({
14
16
  enabled: z.boolean().optional().describe("Filter by enabled status"),
15
17
  name: z.string().optional().describe("Filter by name (partial match)"),
18
+ scheduleType: z
19
+ .enum(["recurring", "one_time"])
20
+ .optional()
21
+ .describe("Filter by schedule type"),
22
+ hideCompleted: z
23
+ .boolean()
24
+ .default(true)
25
+ .optional()
26
+ .describe("Hide completed one-time schedules (default: true)"),
16
27
  }),
17
28
  outputSchema: z.object({
18
29
  yourAgentId: z.string().uuid().optional(),
@@ -35,6 +46,7 @@ export const registerListSchedulesTool = (server: McpServer) => {
35
46
  nextRunAt: z.string().optional(),
36
47
  createdByAgentId: z.string().optional(),
37
48
  timezone: z.string(),
49
+ scheduleType: z.string(),
38
50
  createdAt: z.string(),
39
51
  lastUpdatedAt: z.string(),
40
52
  }),
@@ -42,7 +54,7 @@ export const registerListSchedulesTool = (server: McpServer) => {
42
54
  count: z.number(),
43
55
  }),
44
56
  },
45
- async ({ enabled, name }, requestInfo, _meta) => {
57
+ async ({ enabled, name, scheduleType, hideCompleted }, requestInfo, _meta) => {
46
58
  if (!requestInfo.agentId) {
47
59
  return {
48
60
  content: [{ type: "text", text: 'Agent ID not found. Set the "X-Agent-ID" header.' }],
@@ -56,7 +68,7 @@ export const registerListSchedulesTool = (server: McpServer) => {
56
68
  }
57
69
 
58
70
  try {
59
- const schedules = getScheduledTasks({ enabled, name });
71
+ const schedules = getScheduledTasks({ enabled, name, scheduleType, hideCompleted });
60
72
  const count = schedules.length;
61
73
  const statusSummary =
62
74
  count === 0 ? "No schedules found." : `Found ${count} schedule${count === 1 ? "" : "s"}.`;
@@ -64,10 +76,14 @@ export const registerListSchedulesTool = (server: McpServer) => {
64
76
  // Format for text output
65
77
  const scheduleList = schedules
66
78
  .map((s) => {
67
- const schedule = s.cronExpression || `every ${s.intervalMs}ms`;
79
+ const type = s.scheduleType === "one_time" ? "one-time" : "recurring";
80
+ const schedule =
81
+ s.scheduleType === "one_time"
82
+ ? `runs at ${s.nextRunAt || s.lastRunAt || "unknown"}`
83
+ : s.cronExpression || `every ${s.intervalMs}ms`;
68
84
  const status = s.enabled ? "enabled" : "disabled";
69
85
  const nextRun = s.nextRunAt ? `next: ${s.nextRunAt}` : "not scheduled";
70
- return `- ${s.name} (${status}) [${schedule}] ${nextRun}`;
86
+ return `- ${s.name} (${status}, ${type}) [${schedule}] ${nextRun}`;
71
87
  })
72
88
  .join("\n");
73
89
 
@@ -9,6 +9,7 @@ export const registerRunScheduleNowTool = (server: McpServer) => {
9
9
  "run-schedule-now",
10
10
  {
11
11
  title: "Run Schedule Now",
12
+ annotations: { destructiveHint: false },
12
13
  description:
13
14
  "Immediately execute a scheduled task, creating a task right away. Does not affect the regular schedule timing.",
14
15
  inputSchema: z.object({
@@ -15,6 +15,7 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
15
15
  "update-schedule",
16
16
  {
17
17
  title: "Update Scheduled Task",
18
+ annotations: { idempotentHint: true },
18
19
  description:
19
20
  "Update an existing scheduled task. Only the creator or lead agent can update schedules.",
20
21
  inputSchema: z.object({
@@ -31,6 +32,11 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
31
32
  targetAgentId: z.string().uuid().nullable().optional().describe("New target agent ID"),
32
33
  timezone: z.string().optional().describe("New timezone"),
33
34
  enabled: z.boolean().optional().describe("Enable or disable the schedule"),
35
+ model: z
36
+ .enum(["haiku", "sonnet", "opus"])
37
+ .nullable()
38
+ .optional()
39
+ .describe("Model to use for tasks created by this schedule. Set to null to clear."),
34
40
  }),
35
41
  outputSchema: z.object({
36
42
  yourAgentId: z.string().uuid().optional(),
@@ -53,6 +59,8 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
53
59
  nextRunAt: z.string().optional(),
54
60
  createdByAgentId: z.string().optional(),
55
61
  timezone: z.string(),
62
+ model: z.string().optional(),
63
+ scheduleType: z.string(),
56
64
  createdAt: z.string(),
57
65
  lastUpdatedAt: z.string(),
58
66
  })
@@ -74,6 +82,7 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
74
82
  targetAgentId,
75
83
  timezone,
76
84
  enabled,
85
+ model,
77
86
  },
78
87
  requestInfo,
79
88
  _meta,
@@ -120,6 +129,22 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
120
129
  };
121
130
  }
122
131
 
132
+ // Reject updates on completed one-time schedules
133
+ if (schedule.scheduleType === "one_time" && !schedule.enabled && schedule.lastRunAt) {
134
+ return {
135
+ content: [
136
+ {
137
+ type: "text",
138
+ text: `One-time schedule "${schedule.name}" has already executed. Create a new one instead.`,
139
+ },
140
+ ],
141
+ structuredContent: {
142
+ success: false,
143
+ message: `One-time schedule "${schedule.name}" has already executed. Create a new one instead.`,
144
+ },
145
+ };
146
+ }
147
+
123
148
  // Validate new cron expression if provided
124
149
  if (cronExpression) {
125
150
  try {
@@ -181,24 +206,31 @@ export const registerUpdateScheduleTool = (server: McpServer) => {
181
206
  if (targetAgentId !== undefined) updateData.targetAgentId = targetAgentId;
182
207
  if (timezone !== undefined) updateData.timezone = timezone;
183
208
  if (enabled !== undefined) updateData.enabled = enabled;
209
+ if (model !== undefined) updateData.model = model;
210
+
211
+ // Recalculate nextRunAt based on schedule type
212
+ if (schedule.scheduleType === "one_time") {
213
+ // One-time schedules: no recalculation of nextRunAt via cron/interval
214
+ if (enabled === false) {
215
+ updateData.nextRunAt = undefined;
216
+ }
217
+ } else {
218
+ const needsNextRunRecalc =
219
+ cronExpression !== undefined ||
220
+ intervalMs !== undefined ||
221
+ timezone !== undefined ||
222
+ (enabled === true && !schedule.enabled);
184
223
 
185
- // Recalculate nextRunAt if cron/interval/timezone changes or schedule is re-enabled
186
- const needsNextRunRecalc =
187
- cronExpression !== undefined ||
188
- intervalMs !== undefined ||
189
- timezone !== undefined ||
190
- (enabled === true && !schedule.enabled);
191
-
192
- if (needsNextRunRecalc && enabled !== false) {
193
- const tempSchedule = {
194
- cronExpression: cronExpression ?? schedule.cronExpression,
195
- intervalMs: intervalMs ?? schedule.intervalMs,
196
- timezone: timezone ?? schedule.timezone,
197
- } as Parameters<typeof calculateNextRun>[0];
198
- updateData.nextRunAt = calculateNextRun(tempSchedule, new Date());
199
- } else if (enabled === false) {
200
- // When disabling, clear nextRunAt
201
- updateData.nextRunAt = undefined;
224
+ if (needsNextRunRecalc && enabled !== false) {
225
+ const tempSchedule = {
226
+ cronExpression: cronExpression ?? schedule.cronExpression,
227
+ intervalMs: intervalMs ?? schedule.intervalMs,
228
+ timezone: timezone ?? schedule.timezone,
229
+ } as Parameters<typeof calculateNextRun>[0];
230
+ updateData.nextRunAt = calculateNextRun(tempSchedule, new Date());
231
+ } else if (enabled === false) {
232
+ updateData.nextRunAt = undefined;
233
+ }
202
234
  }
203
235
 
204
236
  const updated = updateScheduledTask(schedule.id, updateData);