@desplega.ai/agent-swarm 1.49.0 → 1.52.0

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 (547) hide show
  1. package/README.md +1 -1
  2. package/openapi.json +2070 -728
  3. package/package.json +10 -1
  4. package/src/agentmail/handlers.ts +65 -10
  5. package/src/agentmail/templates.ts +111 -0
  6. package/src/be/db.ts +1233 -7
  7. package/src/be/migrations/014_prompt_templates.sql +33 -0
  8. package/src/be/migrations/015_workflow_workspace.sql +3 -0
  9. package/src/be/migrations/016_active_session_runner_session.sql +4 -0
  10. package/src/be/migrations/017_channel_activity_cursors.sql +6 -0
  11. package/src/be/migrations/018_fix_seed_double_version.sql +30 -0
  12. package/src/be/migrations/019_skills.sql +65 -0
  13. package/src/be/migrations/020_approval_requests.sql +41 -0
  14. package/src/be/seed.ts +62 -0
  15. package/src/be/skill-parser.ts +70 -0
  16. package/src/be/skill-sync.ts +106 -0
  17. package/src/commands/runner.ts +320 -132
  18. package/src/commands/templates.ts +172 -0
  19. package/src/github/handlers.ts +292 -77
  20. package/src/github/mentions-aliases.test.ts +73 -0
  21. package/src/github/mentions.test.ts +3 -3
  22. package/src/github/mentions.ts +32 -6
  23. package/src/github/templates.ts +398 -0
  24. package/src/gitlab/handlers.ts +63 -22
  25. package/src/gitlab/templates.ts +140 -0
  26. package/src/heartbeat/heartbeat.ts +19 -10
  27. package/src/heartbeat/templates.ts +30 -0
  28. package/src/http/active-sessions.ts +27 -0
  29. package/src/http/approval-requests.ts +247 -0
  30. package/src/http/config.ts +3 -3
  31. package/src/http/index.ts +9 -2
  32. package/src/http/poll.ts +135 -14
  33. package/src/http/prompt-templates.ts +412 -0
  34. package/src/http/schedules.ts +35 -0
  35. package/src/http/skills.ts +479 -0
  36. package/src/http/workflows.ts +8 -0
  37. package/src/linear/sync.ts +28 -4
  38. package/src/linear/templates.ts +47 -0
  39. package/src/prompts/base-prompt.ts +41 -490
  40. package/src/prompts/registry.ts +57 -0
  41. package/src/prompts/resolver.ts +296 -0
  42. package/src/prompts/session-templates.ts +604 -0
  43. package/src/providers/claude-adapter.ts +15 -2
  44. package/src/providers/pi-mono-extension.ts +5 -1
  45. package/src/scheduler/scheduler.ts +125 -91
  46. package/src/server.ts +44 -0
  47. package/src/slack/assistant.ts +7 -4
  48. package/src/slack/channel-activity.ts +177 -0
  49. package/src/slack/handlers.ts +21 -6
  50. package/src/slack/templates.ts +55 -0
  51. package/src/tests/approval-requests.test.ts +735 -0
  52. package/src/tests/artifact-sdk.test.ts +12 -12
  53. package/src/tests/base-prompt.test.ts +49 -49
  54. package/src/tests/channel-activity.test.ts +363 -0
  55. package/src/tests/heartbeat.test.ts +1 -0
  56. package/src/tests/linear-webhook.test.ts +7 -3
  57. package/src/tests/pool-session-logs.test.ts +199 -0
  58. package/src/tests/prompt-template-github.test.ts +682 -0
  59. package/src/tests/prompt-template-remaining.test.ts +504 -0
  60. package/src/tests/prompt-template-resolver.test.ts +621 -0
  61. package/src/tests/prompt-template-session.test.ts +363 -0
  62. package/src/tests/prompt-templates-db.test.ts +616 -0
  63. package/src/tests/self-improvement.test.ts +8 -7
  64. package/src/tests/skill-parser.test.ts +178 -0
  65. package/src/tests/skill-sync.test.ts +171 -0
  66. package/src/tests/slack-metadata-inheritance.test.ts +1 -1
  67. package/src/tests/slack-thread-followups.test.ts +1 -1
  68. package/src/tests/structured-output.test.ts +0 -4
  69. package/src/tests/tool-annotations.test.ts +2 -1
  70. package/src/tests/update-profile-agentid.test.ts +248 -0
  71. package/src/tests/update-profile-auth.test.ts +195 -0
  72. package/src/tests/workflow-async-v2.test.ts +126 -4
  73. package/src/tests/workflow-definition-validation.test.ts +76 -0
  74. package/src/tests/workflow-executors.test.ts +4 -2
  75. package/src/tests/workflow-retry-v2.test.ts +1 -1
  76. package/src/tests/workflow-schedule-trigger.test.ts +104 -0
  77. package/src/tests/workflow-workspace.test.ts +272 -0
  78. package/src/tools/prompt-templates/delete.ts +86 -0
  79. package/src/tools/prompt-templates/get.ts +89 -0
  80. package/src/tools/prompt-templates/index.ts +5 -0
  81. package/src/tools/prompt-templates/list.ts +95 -0
  82. package/src/tools/prompt-templates/preview.ts +84 -0
  83. package/src/tools/prompt-templates/set.ts +117 -0
  84. package/src/tools/request-human-input.ts +106 -0
  85. package/src/tools/skills/index.ts +11 -0
  86. package/src/tools/skills/skill-create.ts +105 -0
  87. package/src/tools/skills/skill-delete.ts +67 -0
  88. package/src/tools/skills/skill-get.ts +75 -0
  89. package/src/tools/skills/skill-install-remote.ts +152 -0
  90. package/src/tools/skills/skill-install.ts +101 -0
  91. package/src/tools/skills/skill-list.ts +77 -0
  92. package/src/tools/skills/skill-publish.ts +123 -0
  93. package/src/tools/skills/skill-search.ts +43 -0
  94. package/src/tools/skills/skill-sync-remote.ts +128 -0
  95. package/src/tools/skills/skill-uninstall.ts +60 -0
  96. package/src/tools/skills/skill-update.ts +128 -0
  97. package/src/tools/store-progress.ts +22 -4
  98. package/src/tools/task-action.ts +20 -0
  99. package/src/tools/templates.ts +53 -0
  100. package/src/tools/tool-config.ts +23 -0
  101. package/src/tools/update-profile.ts +106 -34
  102. package/src/tools/workflows/create-workflow.ts +19 -1
  103. package/src/tools/workflows/update-workflow.ts +16 -1
  104. package/src/types.ts +109 -2
  105. package/src/workflows/definition.ts +30 -12
  106. package/src/workflows/engine.ts +40 -14
  107. package/src/workflows/executors/agent-task.ts +14 -3
  108. package/src/workflows/executors/human-in-the-loop.ts +160 -0
  109. package/src/workflows/executors/registry.ts +2 -0
  110. package/src/workflows/index.ts +1 -1
  111. package/src/workflows/recovery.ts +72 -0
  112. package/src/workflows/resume.ts +162 -12
  113. package/src/workflows/triggers.ts +31 -2
  114. package/src/workflows/version.ts +2 -0
  115. package/.claude/settings.json +0 -84
  116. package/.claude/settings.local.json +0 -117
  117. package/.dockerignore +0 -61
  118. package/.editorconfig +0 -15
  119. package/.entire/settings.json +0 -4
  120. package/.env.docker.example +0 -56
  121. package/.env.example +0 -78
  122. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -78
  123. package/.github/ISSUE_TEMPLATE/community-template.yml +0 -77
  124. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  125. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -60
  126. package/.github/PULL_REQUEST_TEMPLATE/community-template.md +0 -29
  127. package/.github/workflows/ci.yml +0 -52
  128. package/.github/workflows/docker-and-deploy.yml +0 -132
  129. package/.github/workflows/merge-gate.yml +0 -233
  130. package/.opencode/plugins/entire.ts +0 -133
  131. package/.superset/config.json +0 -6
  132. package/.wts-config.json +0 -4
  133. package/.wts-setup.ts +0 -171
  134. package/CHANGELOG.md +0 -447
  135. package/CLAUDE.md +0 -521
  136. package/CONTRIBUTING.md +0 -315
  137. package/DEPLOYMENT.md +0 -622
  138. package/Dockerfile +0 -65
  139. package/Dockerfile.worker +0 -189
  140. package/MCP.md +0 -841
  141. package/UI.md +0 -40
  142. package/api-entrypoint.sh +0 -56
  143. package/assets/agent-swarm-logo-orange.png +0 -0
  144. package/assets/agent-swarm-logo.png +0 -0
  145. package/assets/agent-swarm.mp4 +0 -0
  146. package/assets/agent-swarm.png +0 -0
  147. package/biome.json +0 -39
  148. package/deploy/DEPLOY.md +0 -60
  149. package/deploy/agent-swarm.service +0 -17
  150. package/deploy/docker-push.ts +0 -30
  151. package/deploy/install.ts +0 -85
  152. package/deploy/prod-db.ts +0 -42
  153. package/deploy/uninstall.ts +0 -12
  154. package/deploy/update.ts +0 -21
  155. package/depot.json +0 -1
  156. package/docker-compose.example.yml +0 -350
  157. package/docker-compose.local.yml +0 -119
  158. package/docker-entrypoint.sh +0 -632
  159. package/docs-site/app/api/search/route.ts +0 -4
  160. package/docs-site/app/docs/[[...slug]]/page.tsx +0 -87
  161. package/docs-site/app/docs/layout.tsx +0 -12
  162. package/docs-site/app/globals.css +0 -24
  163. package/docs-site/app/layout.config.tsx +0 -34
  164. package/docs-site/app/layout.tsx +0 -119
  165. package/docs-site/app/llms-full.txt/route.ts +0 -11
  166. package/docs-site/app/llms.mdx/docs/[[...slug]]/route.ts +0 -24
  167. package/docs-site/app/llms.txt/route.ts +0 -8
  168. package/docs-site/app/page.tsx +0 -5
  169. package/docs-site/app/robots.ts +0 -13
  170. package/docs-site/app/sitemap.ts +0 -37
  171. package/docs-site/components/api-page.client.tsx +0 -4
  172. package/docs-site/components/api-page.tsx +0 -7
  173. package/docs-site/components/mdx/mermaid.tsx +0 -55
  174. package/docs-site/content/docs/(documentation)/architecture/agents.mdx +0 -117
  175. package/docs-site/content/docs/(documentation)/architecture/hooks.mdx +0 -77
  176. package/docs-site/content/docs/(documentation)/architecture/memory.mdx +0 -96
  177. package/docs-site/content/docs/(documentation)/architecture/meta.json +0 -4
  178. package/docs-site/content/docs/(documentation)/architecture/overview.mdx +0 -172
  179. package/docs-site/content/docs/(documentation)/concepts/epics.mdx +0 -98
  180. package/docs-site/content/docs/(documentation)/concepts/meta.json +0 -4
  181. package/docs-site/content/docs/(documentation)/concepts/scheduling.mdx +0 -136
  182. package/docs-site/content/docs/(documentation)/concepts/services.mdx +0 -104
  183. package/docs-site/content/docs/(documentation)/concepts/task-lifecycle.mdx +0 -148
  184. package/docs-site/content/docs/(documentation)/concepts/workflows.mdx +0 -209
  185. package/docs-site/content/docs/(documentation)/contributing.mdx +0 -158
  186. package/docs-site/content/docs/(documentation)/getting-started.mdx +0 -157
  187. package/docs-site/content/docs/(documentation)/guides/agentmail-integration.mdx +0 -79
  188. package/docs-site/content/docs/(documentation)/guides/deployment.mdx +0 -171
  189. package/docs-site/content/docs/(documentation)/guides/github-integration.mdx +0 -81
  190. package/docs-site/content/docs/(documentation)/guides/gitlab-integration.mdx +0 -93
  191. package/docs-site/content/docs/(documentation)/guides/linear-integration.mdx +0 -98
  192. package/docs-site/content/docs/(documentation)/guides/meta.json +0 -13
  193. package/docs-site/content/docs/(documentation)/guides/sentry-integration.mdx +0 -52
  194. package/docs-site/content/docs/(documentation)/guides/slack-integration.mdx +0 -179
  195. package/docs-site/content/docs/(documentation)/guides/x402-payments.mdx +0 -154
  196. package/docs-site/content/docs/(documentation)/index.mdx +0 -65
  197. package/docs-site/content/docs/(documentation)/meta.json +0 -19
  198. package/docs-site/content/docs/(documentation)/reference/cli.mdx +0 -241
  199. package/docs-site/content/docs/(documentation)/reference/environment-variables.mdx +0 -205
  200. package/docs-site/content/docs/(documentation)/reference/mcp-tools.mdx +0 -449
  201. package/docs-site/content/docs/(documentation)/reference/meta.json +0 -4
  202. package/docs-site/content/docs/api-reference/active-sessions.mdx +0 -9
  203. package/docs-site/content/docs/api-reference/agents.mdx +0 -9
  204. package/docs-site/content/docs/api-reference/channels.mdx +0 -9
  205. package/docs-site/content/docs/api-reference/config.mdx +0 -9
  206. package/docs-site/content/docs/api-reference/debug.mdx +0 -9
  207. package/docs-site/content/docs/api-reference/ecosystem.mdx +0 -9
  208. package/docs-site/content/docs/api-reference/epics.mdx +0 -9
  209. package/docs-site/content/docs/api-reference/index.mdx +0 -32
  210. package/docs-site/content/docs/api-reference/memory.mdx +0 -9
  211. package/docs-site/content/docs/api-reference/meta.json +0 -25
  212. package/docs-site/content/docs/api-reference/poll.mdx +0 -9
  213. package/docs-site/content/docs/api-reference/repos.mdx +0 -9
  214. package/docs-site/content/docs/api-reference/schedules.mdx +0 -9
  215. package/docs-site/content/docs/api-reference/session-data.mdx +0 -9
  216. package/docs-site/content/docs/api-reference/stats.mdx +0 -9
  217. package/docs-site/content/docs/api-reference/tasks.mdx +0 -9
  218. package/docs-site/content/docs/api-reference/trackers.mdx +0 -9
  219. package/docs-site/content/docs/api-reference/webhooks.mdx +0 -9
  220. package/docs-site/content/docs/api-reference/workflows.mdx +0 -9
  221. package/docs-site/content/docs/meta.json +0 -3
  222. package/docs-site/lib/get-llm-text.ts +0 -10
  223. package/docs-site/lib/openapi.ts +0 -23
  224. package/docs-site/lib/source.ts +0 -8
  225. package/docs-site/mdx-components.tsx +0 -13
  226. package/docs-site/next.config.mjs +0 -29
  227. package/docs-site/package.json +0 -35
  228. package/docs-site/pnpm-lock.yaml +0 -5407
  229. package/docs-site/postcss.config.mjs +0 -8
  230. package/docs-site/public/logo.png +0 -0
  231. package/docs-site/scripts/generate-docs.ts +0 -171
  232. package/docs-site/source.config.ts +0 -17
  233. package/docs-site/tsconfig.json +0 -46
  234. package/ecosystem.config.cjs +0 -66
  235. package/landing/next.config.ts +0 -14
  236. package/landing/package.json +0 -31
  237. package/landing/pnpm-lock.yaml +0 -1091
  238. package/landing/postcss.config.mjs +0 -8
  239. package/landing/public/apple-touch-icon.png +0 -0
  240. package/landing/public/favicon.ico +0 -0
  241. package/landing/public/logo.png +0 -0
  242. package/landing/public/og-image.png +0 -0
  243. package/landing/public/omghost-desplega.svg +0 -30
  244. package/landing/public/omghost-openfort.svg +0 -9
  245. package/landing/src/app/actions/waitlist.ts +0 -25
  246. package/landing/src/app/blog/openfort-hackathon/page.tsx +0 -863
  247. package/landing/src/app/blog/page.tsx +0 -162
  248. package/landing/src/app/blog/swarm-metrics/page.tsx +0 -685
  249. package/landing/src/app/examples/page.tsx +0 -174
  250. package/landing/src/app/examples/x402/page.tsx +0 -456
  251. package/landing/src/app/globals.css +0 -122
  252. package/landing/src/app/layout.tsx +0 -134
  253. package/landing/src/app/page.tsx +0 -27
  254. package/landing/src/app/robots.ts +0 -13
  255. package/landing/src/app/sitemap.ts +0 -44
  256. package/landing/src/components/architecture.tsx +0 -163
  257. package/landing/src/components/cta.tsx +0 -52
  258. package/landing/src/components/features.tsx +0 -160
  259. package/landing/src/components/footer.tsx +0 -100
  260. package/landing/src/components/hero.tsx +0 -217
  261. package/landing/src/components/how-it-works.tsx +0 -165
  262. package/landing/src/components/navbar.tsx +0 -147
  263. package/landing/src/components/waitlist.tsx +0 -110
  264. package/landing/src/components/why-choose.tsx +0 -149
  265. package/landing/src/components/workshops.tsx +0 -328
  266. package/landing/src/lib/utils.ts +0 -6
  267. package/landing/tsconfig.json +0 -41
  268. package/misc/transcripts/2026-03-09-pi-mono-e2e-verification.md +0 -154
  269. package/new-ui/CLAUDE.md +0 -92
  270. package/new-ui/README.md +0 -73
  271. package/new-ui/biome.json +0 -42
  272. package/new-ui/components.json +0 -21
  273. package/new-ui/index.html +0 -25
  274. package/new-ui/package.json +0 -49
  275. package/new-ui/pnpm-lock.yaml +0 -4845
  276. package/new-ui/public/logo.png +0 -0
  277. package/new-ui/src/api/client.ts +0 -814
  278. package/new-ui/src/api/hooks/index.ts +0 -64
  279. package/new-ui/src/api/hooks/use-agents.ts +0 -58
  280. package/new-ui/src/api/hooks/use-channels.ts +0 -115
  281. package/new-ui/src/api/hooks/use-config-api.ts +0 -46
  282. package/new-ui/src/api/hooks/use-costs.ts +0 -122
  283. package/new-ui/src/api/hooks/use-db-query.ts +0 -29
  284. package/new-ui/src/api/hooks/use-epics.ts +0 -75
  285. package/new-ui/src/api/hooks/use-repos.ts +0 -61
  286. package/new-ui/src/api/hooks/use-schedules.ts +0 -81
  287. package/new-ui/src/api/hooks/use-services.ts +0 -16
  288. package/new-ui/src/api/hooks/use-stats.ts +0 -27
  289. package/new-ui/src/api/hooks/use-tasks.ts +0 -89
  290. package/new-ui/src/api/hooks/use-workflows.ts +0 -109
  291. package/new-ui/src/api/types.ts +0 -549
  292. package/new-ui/src/app/App.tsx +0 -13
  293. package/new-ui/src/app/providers.tsx +0 -32
  294. package/new-ui/src/app/router.tsx +0 -52
  295. package/new-ui/src/components/layout/app-header.tsx +0 -47
  296. package/new-ui/src/components/layout/app-sidebar.tsx +0 -128
  297. package/new-ui/src/components/layout/breadcrumbs.tsx +0 -57
  298. package/new-ui/src/components/layout/config-guard.tsx +0 -22
  299. package/new-ui/src/components/layout/root-layout.tsx +0 -40
  300. package/new-ui/src/components/layout/swarm-switcher.tsx +0 -85
  301. package/new-ui/src/components/shared/command-menu.tsx +0 -131
  302. package/new-ui/src/components/shared/data-grid.tsx +0 -141
  303. package/new-ui/src/components/shared/empty-state.tsx +0 -24
  304. package/new-ui/src/components/shared/error-boundary.tsx +0 -72
  305. package/new-ui/src/components/shared/json-viewer.tsx +0 -47
  306. package/new-ui/src/components/shared/name-connection-modal.tsx +0 -99
  307. package/new-ui/src/components/shared/page-skeleton.tsx +0 -16
  308. package/new-ui/src/components/shared/session-log-viewer.tsx +0 -364
  309. package/new-ui/src/components/shared/stats-bar.tsx +0 -132
  310. package/new-ui/src/components/shared/status-badge.tsx +0 -131
  311. package/new-ui/src/components/shared/usage-summary.tsx +0 -179
  312. package/new-ui/src/components/ui/alert-dialog.tsx +0 -176
  313. package/new-ui/src/components/ui/alert.tsx +0 -60
  314. package/new-ui/src/components/ui/avatar.tsx +0 -96
  315. package/new-ui/src/components/ui/badge.tsx +0 -46
  316. package/new-ui/src/components/ui/button.tsx +0 -62
  317. package/new-ui/src/components/ui/card.tsx +0 -75
  318. package/new-ui/src/components/ui/command.tsx +0 -160
  319. package/new-ui/src/components/ui/dialog.tsx +0 -143
  320. package/new-ui/src/components/ui/dropdown-menu.tsx +0 -226
  321. package/new-ui/src/components/ui/input.tsx +0 -21
  322. package/new-ui/src/components/ui/label.tsx +0 -19
  323. package/new-ui/src/components/ui/progress.tsx +0 -26
  324. package/new-ui/src/components/ui/scroll-area.tsx +0 -54
  325. package/new-ui/src/components/ui/select.tsx +0 -175
  326. package/new-ui/src/components/ui/separator.tsx +0 -28
  327. package/new-ui/src/components/ui/sheet.tsx +0 -132
  328. package/new-ui/src/components/ui/sidebar.tsx +0 -691
  329. package/new-ui/src/components/ui/skeleton.tsx +0 -13
  330. package/new-ui/src/components/ui/sonner.tsx +0 -35
  331. package/new-ui/src/components/ui/switch.tsx +0 -33
  332. package/new-ui/src/components/ui/table.tsx +0 -92
  333. package/new-ui/src/components/ui/tabs.tsx +0 -79
  334. package/new-ui/src/components/ui/textarea.tsx +0 -18
  335. package/new-ui/src/components/ui/tooltip.tsx +0 -51
  336. package/new-ui/src/components/workflows/action-node.tsx +0 -53
  337. package/new-ui/src/components/workflows/condition-node.tsx +0 -50
  338. package/new-ui/src/components/workflows/graph-utils.ts +0 -124
  339. package/new-ui/src/components/workflows/json-tree.tsx +0 -189
  340. package/new-ui/src/components/workflows/node-styles.ts +0 -10
  341. package/new-ui/src/components/workflows/step-detail-sheet.tsx +0 -87
  342. package/new-ui/src/components/workflows/trigger-node.tsx +0 -41
  343. package/new-ui/src/components/workflows/workflow-graph.tsx +0 -65
  344. package/new-ui/src/hooks/use-auto-scroll.ts +0 -82
  345. package/new-ui/src/hooks/use-config.ts +0 -203
  346. package/new-ui/src/hooks/use-keyboard-shortcuts.ts +0 -41
  347. package/new-ui/src/hooks/use-mobile.ts +0 -19
  348. package/new-ui/src/hooks/use-theme.ts +0 -60
  349. package/new-ui/src/lib/config.ts +0 -188
  350. package/new-ui/src/lib/slugs.ts +0 -71
  351. package/new-ui/src/lib/utils.ts +0 -120
  352. package/new-ui/src/main.tsx +0 -11
  353. package/new-ui/src/pages/agents/[id]/page.tsx +0 -492
  354. package/new-ui/src/pages/agents/page.tsx +0 -134
  355. package/new-ui/src/pages/chat/page.tsx +0 -674
  356. package/new-ui/src/pages/config/page.tsx +0 -1109
  357. package/new-ui/src/pages/dashboard/page.tsx +0 -454
  358. package/new-ui/src/pages/debug/page.tsx +0 -275
  359. package/new-ui/src/pages/epics/[id]/page.tsx +0 -809
  360. package/new-ui/src/pages/epics/page.tsx +0 -321
  361. package/new-ui/src/pages/not-found/page.tsx +0 -18
  362. package/new-ui/src/pages/repos/page.tsx +0 -369
  363. package/new-ui/src/pages/schedules/[id]/page.tsx +0 -664
  364. package/new-ui/src/pages/schedules/page.tsx +0 -477
  365. package/new-ui/src/pages/services/page.tsx +0 -128
  366. package/new-ui/src/pages/tasks/[id]/page.tsx +0 -670
  367. package/new-ui/src/pages/tasks/page.tsx +0 -592
  368. package/new-ui/src/pages/usage/page.tsx +0 -195
  369. package/new-ui/src/pages/workflow-runs/[id]/page.tsx +0 -363
  370. package/new-ui/src/pages/workflows/[id]/page.tsx +0 -417
  371. package/new-ui/src/pages/workflows/page.tsx +0 -266
  372. package/new-ui/src/styles/ag-grid.css +0 -36
  373. package/new-ui/src/styles/globals.css +0 -213
  374. package/new-ui/test-results/.last-run.json +0 -4
  375. package/new-ui/tsconfig.app.json +0 -34
  376. package/new-ui/tsconfig.json +0 -4
  377. package/new-ui/tsconfig.node.json +0 -26
  378. package/new-ui/vercel.json +0 -4
  379. package/new-ui/vite.config.ts +0 -28
  380. package/plugin/README.md +0 -1
  381. package/plugin/build-pi-skills.ts +0 -233
  382. package/plugin/hooks/hooks.json +0 -71
  383. package/prek.toml +0 -75
  384. package/pyproject.toml +0 -9
  385. package/scripts/check-db-boundary.sh +0 -60
  386. package/scripts/e2e-docker-provider.ts +0 -820
  387. package/scripts/e2e-io-schemas-test.ts +0 -807
  388. package/scripts/e2e-provider-test.ts +0 -220
  389. package/scripts/e2e-workflow-redesign.sh +0 -229
  390. package/scripts/e2e-workflow-test.sh +0 -285
  391. package/scripts/e2e-workflow-test.ts +0 -857
  392. package/scripts/generate-mcp-docs.ts +0 -415
  393. package/scripts/generate-openapi.ts +0 -26
  394. package/scripts/measure-tool-tokens.ts +0 -118
  395. package/scripts/x402-e2e-test.ts +0 -195
  396. package/scripts/x402-test-server.ts +0 -236
  397. package/scripts/x402-testnet-e2e.ts +0 -668
  398. package/slack-manifest.json +0 -88
  399. package/templates-ui/README.md +0 -46
  400. package/templates-ui/components.json +0 -17
  401. package/templates-ui/eslint.config.mjs +0 -18
  402. package/templates-ui/next.config.ts +0 -7
  403. package/templates-ui/package.json +0 -35
  404. package/templates-ui/pnpm-lock.yaml +0 -4571
  405. package/templates-ui/postcss.config.mjs +0 -7
  406. package/templates-ui/public/file.svg +0 -1
  407. package/templates-ui/public/globe.svg +0 -1
  408. package/templates-ui/public/logo.png +0 -0
  409. package/templates-ui/public/next.svg +0 -1
  410. package/templates-ui/public/vercel.svg +0 -1
  411. package/templates-ui/public/window.svg +0 -1
  412. package/templates-ui/src/app/[category]/[name]/page.tsx +0 -89
  413. package/templates-ui/src/app/api/templates/[...slug]/route.ts +0 -52
  414. package/templates-ui/src/app/api/templates/route.ts +0 -18
  415. package/templates-ui/src/app/builder/page.tsx +0 -37
  416. package/templates-ui/src/app/globals.css +0 -94
  417. package/templates-ui/src/app/layout.tsx +0 -79
  418. package/templates-ui/src/app/page.tsx +0 -38
  419. package/templates-ui/src/app/robots.ts +0 -11
  420. package/templates-ui/src/app/sitemap.ts +0 -31
  421. package/templates-ui/src/components/compose-builder.tsx +0 -442
  422. package/templates-ui/src/components/compose-preview.tsx +0 -117
  423. package/templates-ui/src/components/file-preview.tsx +0 -77
  424. package/templates-ui/src/components/footer.tsx +0 -40
  425. package/templates-ui/src/components/header.tsx +0 -41
  426. package/templates-ui/src/components/template-card.tsx +0 -87
  427. package/templates-ui/src/components/template-detail.tsx +0 -125
  428. package/templates-ui/src/components/template-gallery.tsx +0 -263
  429. package/templates-ui/src/components/ui/badge.tsx +0 -36
  430. package/templates-ui/src/components/ui/button.tsx +0 -57
  431. package/templates-ui/src/components/ui/card.tsx +0 -76
  432. package/templates-ui/src/components/ui/separator.tsx +0 -31
  433. package/templates-ui/src/components/ui/tooltip.tsx +0 -32
  434. package/templates-ui/src/lib/compose-generator.ts +0 -241
  435. package/templates-ui/src/lib/templates.ts +0 -137
  436. package/templates-ui/src/lib/utils.ts +0 -6
  437. package/templates-ui/tsconfig.json +0 -34
  438. package/thoughts/research/2026-02-28-openfort-viem-x402-research.md +0 -679
  439. package/thoughts/research/2026-02-28-x402-payments-research.md +0 -686
  440. package/thoughts/researcher/plans/2026-02-20-agent-self-improvement-plan.md +0 -282
  441. package/thoughts/researcher/research/2026-02-20-agent-self-improvement.md +0 -492
  442. package/thoughts/shared/plans/.gitkeep +0 -0
  443. package/thoughts/shared/plans/2025-12-18-slack-integration.md +0 -1195
  444. package/thoughts/shared/plans/2025-12-19-agent-log-streaming.md +0 -732
  445. package/thoughts/shared/plans/2025-12-19-role-based-swarm-plugin.md +0 -361
  446. package/thoughts/shared/plans/2025-12-20-mobile-responsive-ui.md +0 -501
  447. package/thoughts/shared/plans/2025-12-20-startup-team-swarm.md +0 -560
  448. package/thoughts/shared/plans/2025-12-23-runner-level-polling.md +0 -934
  449. package/thoughts/shared/plans/2025-12-23-runner-session-logs.md +0 -1000
  450. package/thoughts/shared/plans/2025-12-23-worker-lead-spawn-triggers.md +0 -568
  451. package/thoughts/shared/plans/2026-01-09-inverse-teleport.md +0 -1516
  452. package/thoughts/shared/plans/2026-01-12-agent-rename-pm2-control.md +0 -1133
  453. package/thoughts/shared/plans/2026-01-12-github-app-integration.md +0 -380
  454. package/thoughts/shared/plans/2026-01-12-lead-inbox-model.md +0 -876
  455. package/thoughts/shared/plans/2026-01-12-ralph-wiggum-integration.md +0 -463
  456. package/thoughts/shared/plans/2026-01-13-agent-concurrency.md +0 -691
  457. package/thoughts/shared/plans/2026-01-13-github-assignment-handling.md +0 -690
  458. package/thoughts/shared/plans/2026-01-13-prevent-duplicate-trigger-processing.md +0 -1071
  459. package/thoughts/shared/plans/2026-01-14-fix-slack-thread-context.md +0 -507
  460. package/thoughts/shared/plans/2026-01-15-scheduled-tasks-implementation.md +0 -565
  461. package/thoughts/shared/plans/2026-01-15-usage-cost-tracking-ui.md +0 -1479
  462. package/thoughts/shared/plans/2026-01-16-epics-feature-implementation.md +0 -1230
  463. package/thoughts/shared/plans/2026-02-26-mcp-tool-context-reduction.md +0 -282
  464. package/thoughts/shared/plans/2026-03-02-claude-context-mode-integration.md +0 -328
  465. package/thoughts/shared/plans/2026-03-02-code-level-heartbeat.md +0 -224
  466. package/thoughts/shared/research/.gitkeep +0 -0
  467. package/thoughts/shared/research/2025-01-09-inverse-teleport-plan-review.md +0 -420
  468. package/thoughts/shared/research/2025-12-18-slack-integration.md +0 -442
  469. package/thoughts/shared/research/2025-12-19-agent-log-streaming.md +0 -339
  470. package/thoughts/shared/research/2025-12-19-agent-secrets-cli-research.md +0 -390
  471. package/thoughts/shared/research/2025-12-21-gemini-cli-integration.md +0 -376
  472. package/thoughts/shared/research/2025-12-22-runner-loop-architecture.md +0 -582
  473. package/thoughts/shared/research/2025-12-22-setup-experience-improvements.md +0 -264
  474. package/thoughts/shared/research/2026-01-13-lead-duplicate-trigger-processing.md +0 -223
  475. package/thoughts/shared/research/2026-01-14-lead-slack-thread-context.md +0 -277
  476. package/thoughts/shared/research/2026-01-15-ai-tracker-agent-swarm-integration.md +0 -376
  477. package/thoughts/shared/research/2026-01-15-auto-starting-processes-in-worker-containers.md +0 -787
  478. package/thoughts/shared/research/2026-01-15-scheduled-tasks.md +0 -390
  479. package/thoughts/shared/research/2026-01-16-epics-feature-research.md +0 -437
  480. package/thoughts/shared/research/2026-02-26-cliffy-mcp-tools.md +0 -159
  481. package/thoughts/shared/research/2026-03-03-database-migration-system-refactor.md +0 -337
  482. package/thoughts/swarm-researcher/plans/2026-02-23-openclaw-improvements-plan.md +0 -778
  483. package/thoughts/swarm-researcher/plans/2026-02-26-artifacts-localtunnel-plan.md +0 -1269
  484. package/thoughts/swarm-researcher/research/2026-02-23-openclaw-vs-agent-swarm-comparison.md +0 -411
  485. package/thoughts/swarm-researcher/research/2026-02-26-artifacts-localtunnel.md +0 -724
  486. package/thoughts/taras/brainstorms/2026-03-20-prompt-template-registry.md +0 -443
  487. package/thoughts/taras/brainstorms/2026-03-20-setup-cli-onboarding.md +0 -307
  488. package/thoughts/taras/plans/2026-01-22-agent-swarm-schemas.md +0 -98
  489. package/thoughts/taras/plans/2026-01-28-per-worker-claude-md.md +0 -617
  490. package/thoughts/taras/plans/2026-01-28-sentry-cli-integration.md +0 -214
  491. package/thoughts/taras/plans/2026-02-20-auto-improvement.md +0 -803
  492. package/thoughts/taras/plans/2026-02-20-env-management.md +0 -538
  493. package/thoughts/taras/plans/2026-02-20-memory-system.md +0 -882
  494. package/thoughts/taras/plans/2026-02-20-repos-knowledge.md +0 -806
  495. package/thoughts/taras/plans/2026-02-20-session-attach.md +0 -647
  496. package/thoughts/taras/plans/2026-02-20-worker-identity.md +0 -820
  497. package/thoughts/taras/plans/2026-02-25-feat-new-ui-visual-redesign-plan.md +0 -768
  498. package/thoughts/taras/plans/2026-03-04-fix-buildSystemPrompt-missing-fields.md +0 -77
  499. package/thoughts/taras/plans/2026-03-04-new-ui-missing-actions.md +0 -543
  500. package/thoughts/taras/plans/2026-03-06-one-time-scheduled-tasks.md +0 -373
  501. package/thoughts/taras/plans/2026-03-08-memory-self-improvement-enhancements.md +0 -512
  502. package/thoughts/taras/plans/2026-03-08-pi-mono-provider-implementation.md +0 -919
  503. package/thoughts/taras/plans/2026-03-09-templates-registry.md +0 -723
  504. package/thoughts/taras/plans/2026-03-10-task-working-directory.md +0 -371
  505. package/thoughts/taras/plans/2026-03-11-archil-per-agent-write-strategy.md +0 -621
  506. package/thoughts/taras/plans/2026-03-12-eliminate-inbox-route-to-tasks.md +0 -61
  507. package/thoughts/taras/plans/2026-03-12-slack-thread-followup-additive.md +0 -488
  508. package/thoughts/taras/plans/2026-03-13-slack-ai-improvements.md +0 -644
  509. package/thoughts/taras/plans/2026-03-16-route-wrapper-openapi.md +0 -636
  510. package/thoughts/taras/plans/2026-03-17-multi-api-config.md +0 -444
  511. package/thoughts/taras/plans/2026-03-18-agent-fs-integration.md +0 -591
  512. package/thoughts/taras/plans/2026-03-18-debug-db-explorer.md +0 -446
  513. package/thoughts/taras/plans/2026-03-18-workflow-redesign.md +0 -987
  514. package/thoughts/taras/plans/2026-03-19-compound-learnings.md +0 -403
  515. package/thoughts/taras/plans/2026-03-19-ticket-tracker-linear-integration.md +0 -860
  516. package/thoughts/taras/plans/2026-03-19-workflow-io-schemas-and-bugs.md +0 -899
  517. package/thoughts/taras/plans/2026-03-20-setup-cli-onboarding.md +0 -874
  518. package/thoughts/taras/plans/2026-03-20-workflow-structured-output-validation-workspace.md +0 -723
  519. package/thoughts/taras/research/2026-01-22-vercel-cli-integration.md +0 -287
  520. package/thoughts/taras/research/2026-01-27-excessive-polling-issue.md +0 -311
  521. package/thoughts/taras/research/2026-01-28-per-worker-claude-md.md +0 -383
  522. package/thoughts/taras/research/2026-01-28-sentry-cli-integration.md +0 -240
  523. package/thoughts/taras/research/2026-02-19-agent-native-swarm-architecture.md +0 -390
  524. package/thoughts/taras/research/2026-02-19-swarm-gaps-implementation.md +0 -594
  525. package/thoughts/taras/research/2026-02-25-dashboard-ui-design-best-practices.md +0 -825
  526. package/thoughts/taras/research/2026-02-26-task-detail-page-redesign.md +0 -393
  527. package/thoughts/taras/research/2026-03-03-new-ui-missing-actions.md +0 -168
  528. package/thoughts/taras/research/2026-03-05-pi-mono-provider-research.md +0 -230
  529. package/thoughts/taras/research/2026-03-06-workflow-engine-design.md +0 -445
  530. package/thoughts/taras/research/2026-03-08-drive-loop-concept.md +0 -375
  531. package/thoughts/taras/research/2026-03-08-pi-mono-deep-dive.md +0 -869
  532. package/thoughts/taras/research/2026-03-09-templates-registry.md +0 -373
  533. package/thoughts/taras/research/2026-03-10-agent-working-directory.md +0 -223
  534. package/thoughts/taras/research/2026-03-10-configurable-event-prompts.md +0 -339
  535. package/thoughts/taras/research/2026-03-11-archil-production-setup.md +0 -181
  536. package/thoughts/taras/research/2026-03-11-archil-shared-disk-write-strategies.md +0 -437
  537. package/thoughts/taras/research/2026-03-13-slack-ai-features.md +0 -258
  538. package/thoughts/taras/research/2026-03-16-openapi-docs-generation.md +0 -335
  539. package/thoughts/taras/research/2026-03-16-route-wrapper-openapi.md +0 -670
  540. package/thoughts/taras/research/2026-03-16-slack-thread-followups-e2e.md +0 -54
  541. package/thoughts/taras/research/2026-03-18-agent-fs-integration.md +0 -558
  542. package/thoughts/taras/research/2026-03-18-linear-integration-finalization.md +0 -526
  543. package/thoughts/taras/research/2026-03-18-workflow-redesign.md +0 -797
  544. package/thoughts/taras/research/2026-03-19-workflow-node-io-schemas-and-bugs.md +0 -563
  545. package/thoughts/taras/research/2026-03-19-workflow-structured-output-validation-workspace.md +0 -486
  546. package/thoughts/taras/research/2026-03-20-prompt-template-registry.md +0 -469
  547. package/tsconfig.json +0 -37
@@ -8,6 +8,7 @@ import {
8
8
  generateDefaultSoulMd,
9
9
  generateDefaultToolsMd,
10
10
  } from "../prompts/defaults.ts";
11
+ import { configureHttpResolver, resolveTemplateAsync } from "../prompts/resolver.ts";
11
12
  import {
12
13
  type CostData,
13
14
  createProviderAdapter,
@@ -19,6 +20,8 @@ import { resolveCredentialPools } from "../utils/credentials.ts";
19
20
  import { prettyPrintLine, prettyPrintStderr } from "../utils/pretty-print.ts";
20
21
  import { detectVcsProvider } from "../vcs/index.ts";
21
22
  import { interpolate } from "../workflows/template.ts";
23
+ // Side-effect import: registers runner trigger/resumption templates
24
+ import "./templates.ts";
22
25
 
23
26
  /** Save PM2 process list for persistence across container restarts */
24
27
  async function savePm2State(role: string): Promise<void> {
@@ -89,6 +92,10 @@ async function ensureRepoForTask(
89
92
  } else {
90
93
  await Bun.$`git clone --branch ${defaultBranch} --single-branch ${url} ${clonePath}`.quiet();
91
94
  }
95
+ // Validate the clone actually created the directory
96
+ if (!existsSync(clonePath)) {
97
+ throw new Error(`Clone command succeeded but directory ${clonePath} does not exist`);
98
+ }
92
99
  console.log(`[${role}] Cloned ${name}`);
93
100
  } else {
94
101
  console.log(`[${role}] Repo ${name} already cloned at ${clonePath}`);
@@ -111,7 +118,9 @@ async function ensureRepoForTask(
111
118
  const errorMsg = (err as Error).message;
112
119
  console.warn(`[${role}] Error setting up repo ${name}: ${errorMsg}`);
113
120
  const warning = `Failed to clone/setup repo "${name}" at ${clonePath}: ${errorMsg}. The repo may not be available. You may need to clone it manually.`;
114
- return { clonePath, claudeMd: null, warning };
121
+ // Only return clonePath if the directory actually exists (clone may have failed)
122
+ const cloneExists = existsSync(clonePath);
123
+ return { clonePath: cloneExists ? clonePath : "", claudeMd: null, warning };
115
124
  }
116
125
  }
117
126
 
@@ -549,34 +558,26 @@ async function resumeTaskViaAPI(config: ApiConfig, taskId: string): Promise<bool
549
558
  }
550
559
 
551
560
  /** Build prompt for a resumed task */
552
- function buildResumePrompt(
561
+ async function buildResumePrompt(
553
562
  task: { id: string; task: string; progress?: string },
554
563
  fmt: (cmd: string) => string = (cmd) => `/${cmd}`,
555
- ): string {
556
- let prompt = `${fmt("work-on-task")} ${task.id}
557
-
558
- **RESUMED TASK** - This task was interrupted during a deployment and is being resumed.
559
-
560
- Task: "${task.task}"`;
561
-
564
+ ): Promise<string> {
562
565
  if (task.progress) {
563
- prompt += `
564
-
565
- Previous Progress:
566
- ${task.progress}
567
-
568
- Continue from where you left off. Review the progress above and complete the remaining work.`;
569
- } else {
570
- prompt += `
571
-
572
- No progress was saved before the interruption. Start the task fresh but be aware files may have been partially modified.`;
566
+ const result = await resolveTemplateAsync("task.resumption.with_progress", {
567
+ work_on_task_cmd: fmt("work-on-task"),
568
+ task_id: task.id,
569
+ task_description: task.task,
570
+ progress: task.progress,
571
+ });
572
+ return result.text;
573
573
  }
574
574
 
575
- prompt += `
576
-
577
- When done, use \`store-progress\` with status: "completed" and include your output.`;
578
-
579
- return prompt;
575
+ const result = await resolveTemplateAsync("task.resumption.no_progress", {
576
+ work_on_task_cmd: fmt("work-on-task"),
577
+ task_id: task.id,
578
+ task_description: task.task,
579
+ });
580
+ return result.text;
580
581
  }
581
582
 
582
583
  /** Setup signal handlers for graceful shutdown */
@@ -671,6 +672,8 @@ interface RunningTask {
671
672
  triggerType?: string;
672
673
  /** Set when the promise resolves, enabling non-blocking completion checks */
673
674
  result: ProviderResult | null;
675
+ /** Deferred cursor updates for channel_activity triggers — committed after success */
676
+ cursorUpdates?: Array<{ channelId: string; ts: string }>;
674
677
  }
675
678
 
676
679
  /** Runner state for tracking concurrent tasks */
@@ -781,6 +784,22 @@ async function saveProviderSessionId(
781
784
  });
782
785
  }
783
786
 
787
+ /** Save provider session ID on the active session (for pool tasks where realTaskId is unknown) */
788
+ async function saveProviderSessionIdOnActiveSession(
789
+ apiUrl: string,
790
+ apiKey: string,
791
+ effectiveTaskId: string,
792
+ providerSessionId: string,
793
+ ): Promise<void> {
794
+ const headers: Record<string, string> = { "Content-Type": "application/json" };
795
+ if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
796
+ await fetch(`${apiUrl}/api/active-sessions/provider-session/${effectiveTaskId}`, {
797
+ method: "PUT",
798
+ headers,
799
+ body: JSON.stringify({ providerSessionId }),
800
+ });
801
+ }
802
+
784
803
  /** Fetch Claude session ID for a task (for --resume) */
785
804
  async function fetchProviderSessionId(
786
805
  apiUrl: string,
@@ -806,6 +825,7 @@ async function registerActiveSession(
806
825
  taskId: string;
807
826
  triggerType: string;
808
827
  taskDescription?: string;
828
+ runnerSessionId?: string;
809
829
  },
810
830
  ): Promise<void> {
811
831
  const headers: Record<string, string> = {
@@ -822,6 +842,7 @@ async function registerActiveSession(
822
842
  taskId: session.taskId,
823
843
  triggerType: session.triggerType,
824
844
  taskDescription: session.taskDescription,
845
+ runnerSessionId: session.runnerSessionId,
825
846
  }),
826
847
  });
827
848
  } catch {
@@ -868,7 +889,8 @@ interface Trigger {
868
889
  | "task_offered"
869
890
  | "unread_mentions"
870
891
  | "pool_tasks_available"
871
- | "epic_progress_changed";
892
+ | "epic_progress_changed"
893
+ | "channel_activity";
872
894
  taskId?: string;
873
895
  task?: unknown;
874
896
  mentionsCount?: number;
@@ -885,8 +907,14 @@ interface Trigger {
885
907
  messages?: Array<{
886
908
  id: string;
887
909
  content: string;
910
+ channelId?: string;
911
+ channelName?: string;
912
+ ts?: string;
913
+ user?: string;
914
+ text?: string;
888
915
  }>;
889
916
  epics?: unknown; // Epic progress updates for lead
917
+ cursorUpdates?: Array<{ channelId: string; ts: string }>; // Deferred cursor commits for channel_activity
890
918
  }
891
919
 
892
920
  /** Options for polling */
@@ -980,11 +1008,11 @@ async function pollForTrigger(opts: PollOptions): Promise<Trigger | null> {
980
1008
  }
981
1009
 
982
1010
  /** Build prompt based on trigger type */
983
- function buildPromptForTrigger(
1011
+ async function buildPromptForTrigger(
984
1012
  trigger: Trigger,
985
1013
  defaultPrompt: string,
986
1014
  fmt: (cmd: string) => string = (cmd) => `/${cmd}`,
987
- ): string {
1015
+ ): Promise<string> {
988
1016
  switch (trigger.type) {
989
1017
  case "task_assigned": {
990
1018
  // Use the work-on-task command with task ID and description
@@ -992,19 +1020,25 @@ function buildPromptForTrigger(
992
1020
  trigger.task && typeof trigger.task === "object" && "task" in trigger.task
993
1021
  ? (trigger.task as { task: string }).task
994
1022
  : null;
995
- let prompt = `${fmt("work-on-task")} ${trigger.taskId}`;
996
- if (taskDesc) {
997
- prompt += `\n\nTask: "${taskDesc}"`;
998
- }
1023
+ const taskDescSection = taskDesc ? `\n\nTask: "${taskDesc}"` : "";
999
1024
 
1000
- // Inject outputSchema instructions if present
1025
+ // Build output instructions — use outputSchema if present, otherwise generic
1001
1026
  const taskObj = trigger.task as Record<string, unknown> | undefined;
1027
+ let outputInstructions: string;
1002
1028
  if (taskObj?.outputSchema && typeof taskObj.outputSchema === "object") {
1003
- prompt += `\n\n**Required Output Format**: When completing this task, you MUST call store-progress with output that is valid JSON conforming to this schema:\n\`\`\`json\n${JSON.stringify(taskObj.outputSchema, null, 2)}\n\`\`\`\nCall store-progress with status "completed" and your JSON output. If your output doesn't match the schema, the tool call will fail and you should fix and retry.`;
1029
+ outputInstructions = `\n\n**Required Output Format**: When completing this task, you MUST call store-progress with output that is valid JSON conforming to this schema:\n\`\`\`json\n${JSON.stringify(taskObj.outputSchema, null, 2)}\n\`\`\`\nCall store-progress with status "completed" and your JSON output. If your output doesn't match the schema, the tool call will fail and you should fix and retry.`;
1004
1030
  } else {
1005
- prompt += `\n\nWhen done, use \`store-progress\` with status: "completed" and include your output.`;
1031
+ outputInstructions =
1032
+ '\n\nWhen done, use `store-progress` with status: "completed" and include your output.';
1006
1033
  }
1007
- return prompt;
1034
+
1035
+ const result = await resolveTemplateAsync("task.trigger.assigned", {
1036
+ work_on_task_cmd: fmt("work-on-task"),
1037
+ task_id: trigger.taskId,
1038
+ task_desc_section: taskDescSection,
1039
+ output_instructions: outputInstructions,
1040
+ });
1041
+ return result.text;
1008
1042
  }
1009
1043
 
1010
1044
  case "task_offered": {
@@ -1013,31 +1047,28 @@ function buildPromptForTrigger(
1013
1047
  trigger.task && typeof trigger.task === "object" && "task" in trigger.task
1014
1048
  ? (trigger.task as { task: string }).task
1015
1049
  : null;
1016
- let prompt = `${fmt("review-offered-task")} ${trigger.taskId}`;
1017
- if (taskDesc) {
1018
- prompt += `\n\nA task has been offered to you:\n"${taskDesc}"`;
1019
- }
1020
- prompt += `\n\nAccept if you have capacity and skills. Reject with a reason if you cannot handle it.`;
1021
- return prompt;
1050
+ const taskDescSection = taskDesc ? `\n\nA task has been offered to you:\n"${taskDesc}"` : "";
1051
+ const result = await resolveTemplateAsync("task.trigger.offered", {
1052
+ review_offered_task_cmd: fmt("review-offered-task"),
1053
+ task_id: trigger.taskId,
1054
+ task_desc_section: taskDescSection,
1055
+ });
1056
+ return result.text;
1022
1057
  }
1023
1058
 
1024
- case "unread_mentions":
1025
- // Check messages - numbered steps for clarity
1026
- return `You have ${trigger.count || "unread"} mention(s) in chat channels.
1027
-
1028
- 1. Use \`read-messages\` with unreadOnly: true to see them
1029
- 2. Respond to questions or requests directed at you
1030
- 3. If a message requires work, create a task using \`send-task\``;
1031
-
1032
- case "pool_tasks_available":
1033
- // Worker: claim a task from the pool - numbered steps for clarity
1034
- return `${trigger.count} task(s) available in the pool.
1035
-
1036
- 1. Run \`get-tasks\` with unassigned: true to browse
1037
- 2. Pick one matching your skills
1038
- 3. Run \`task-action\` with action: "claim" and taskId: "<id>"
1059
+ case "unread_mentions": {
1060
+ const result = await resolveTemplateAsync("task.trigger.unread_mentions", {
1061
+ mention_count: trigger.count || "unread",
1062
+ });
1063
+ return result.text;
1064
+ }
1039
1065
 
1040
- Note: Claims are first-come-first-serve. If claim fails, pick another.`;
1066
+ case "pool_tasks_available": {
1067
+ const result = await resolveTemplateAsync("task.trigger.pool_available", {
1068
+ task_count: trigger.count,
1069
+ });
1070
+ return result.text;
1071
+ }
1041
1072
 
1042
1073
  case "epic_progress_changed": {
1043
1074
  // Lead: Epic progress updated - tasks completed or failed for an active epic
@@ -1074,19 +1105,19 @@ Note: Claims are first-come-first-serve. If claim fails, pick another.`;
1074
1105
  return "Epic progress was updated but no details available. Use `list-epics` to check status.";
1075
1106
  }
1076
1107
 
1077
- let prompt = `## Epic Progress Update\n\n${trigger.count} epic(s) have progress updates:\n\n`;
1078
-
1108
+ // Build epics detail section as a pre-computed variable
1109
+ let epicsDetail = "";
1079
1110
  for (const { epic, finishedTasks } of epics) {
1080
- prompt += `### Epic: "${epic.name}" (${epic.id.slice(0, 8)})\n`;
1081
- prompt += `**Goal:** ${epic.goal}\n`;
1082
- prompt += `**Progress:** ${epic.progress}% complete (${epic.taskStats.completed}/${epic.taskStats.total} tasks)\n`;
1083
- prompt += `**Status:** ${epic.status}\n\n`;
1111
+ epicsDetail += `### Epic: "${epic.name}" (${epic.id.slice(0, 8)})\n`;
1112
+ epicsDetail += `**Goal:** ${epic.goal}\n`;
1113
+ epicsDetail += `**Progress:** ${epic.progress}% complete (${epic.taskStats.completed}/${epic.taskStats.total} tasks)\n`;
1114
+ epicsDetail += `**Status:** ${epic.status}\n\n`;
1084
1115
 
1085
1116
  if (epic.plan) {
1086
- prompt += `**Plan:**\n${epic.plan.slice(0, 2000)}\n\n`;
1117
+ epicsDetail += `**Plan:**\n${epic.plan.slice(0, 2000)}\n\n`;
1087
1118
  }
1088
1119
  if (epic.prd) {
1089
- prompt += `**PRD:**\n${epic.prd.slice(0, 1000)}\n\n`;
1120
+ epicsDetail += `**PRD:**\n${epic.prd.slice(0, 1000)}\n\n`;
1090
1121
  }
1091
1122
 
1092
1123
  // Show finished tasks
@@ -1094,48 +1125,63 @@ Note: Claims are first-come-first-serve. If claim fails, pick another.`;
1094
1125
  const failed = finishedTasks.filter((t) => t.status === "failed");
1095
1126
 
1096
1127
  if (completed.length > 0) {
1097
- prompt += "**Recently Completed:**\n";
1128
+ epicsDetail += "**Recently Completed:**\n";
1098
1129
  for (const t of completed) {
1099
1130
  const agentName = t.agentId ? `Agent ${t.agentId.slice(0, 8)}` : "Unknown";
1100
1131
  const output = t.output ? t.output.slice(0, 150) : "(no output)";
1101
- prompt += `- Task ${t.id.slice(0, 8)} by ${agentName}: "${t.task.slice(0, 80)}"\n`;
1102
- prompt += ` Output: ${output}${t.output && t.output.length > 150 ? "..." : ""}\n`;
1132
+ epicsDetail += `- Task ${t.id.slice(0, 8)} by ${agentName}: "${t.task.slice(0, 80)}"\n`;
1133
+ epicsDetail += ` Output: ${output}${t.output && t.output.length > 150 ? "..." : ""}\n`;
1103
1134
  }
1104
1135
  }
1105
1136
 
1106
1137
  if (failed.length > 0) {
1107
- prompt += "\n**Recently Failed:**\n";
1138
+ epicsDetail += "\n**Recently Failed:**\n";
1108
1139
  for (const t of failed) {
1109
1140
  const agentName = t.agentId ? `Agent ${t.agentId.slice(0, 8)}` : "Unknown";
1110
- prompt += `- Task ${t.id.slice(0, 8)} by ${agentName}: "${t.task.slice(0, 80)}"\n`;
1111
- prompt += ` Reason: ${t.failureReason || "(no reason)"}\n`;
1141
+ epicsDetail += `- Task ${t.id.slice(0, 8)} by ${agentName}: "${t.task.slice(0, 80)}"\n`;
1142
+ epicsDetail += ` Reason: ${t.failureReason || "(no reason)"}\n`;
1112
1143
  }
1113
1144
  }
1114
1145
 
1115
1146
  // Show remaining work
1116
1147
  const { inProgress, pending } = epic.taskStats;
1117
1148
  if (inProgress > 0 || pending > 0) {
1118
- prompt += `\n**Remaining:** ${inProgress} in progress, ${pending} pending\n`;
1149
+ epicsDetail += `\n**Remaining:** ${inProgress} in progress, ${pending} pending\n`;
1119
1150
  }
1120
1151
 
1121
- prompt += "\n---\n\n";
1152
+ epicsDetail += "\n---\n\n";
1122
1153
  }
1123
1154
 
1124
- prompt += `## Your Task: Plan Next Steps
1155
+ const result = await resolveTemplateAsync("task.trigger.epic_progress", {
1156
+ epic_count: trigger.count,
1157
+ epics_detail: epicsDetail,
1158
+ });
1159
+ return result.text;
1160
+ }
1125
1161
 
1126
- For each epic:
1127
- 1. **Review** the completed work and any failures
1128
- 2. **Determine** if the epic goal is met (progress = 100% and all tasks succeeded)
1129
- 3. **If complete:** Use \`update-epic\` to mark status as "completed"
1130
- 4. **If not complete:**
1131
- - Retry failed tasks with \`send-task\` (reassign or modify)
1132
- - Create new tasks for remaining work with \`send-task\` (include epicId)
1133
- - Keep the epic progressing until the goal is achieved
1162
+ case "channel_activity": {
1163
+ const msgs = (trigger.messages || []) as Array<{
1164
+ channelId?: string;
1165
+ channelName?: string;
1166
+ ts?: string;
1167
+ user?: string;
1168
+ text?: string;
1169
+ }>;
1170
+ if (msgs.length === 0) {
1171
+ return "New Slack channel activity detected but no message details available. Use `slack-read` to check recent messages.";
1172
+ }
1134
1173
 
1135
- This is an iterative process - you'll be notified again when more tasks finish.
1136
- The epic should keep progressing until 100% complete and the goal is achieved.`;
1174
+ let messagesDetail = "";
1175
+ for (const msg of msgs) {
1176
+ const channel = msg.channelName ? `#${msg.channelName}` : msg.channelId || "unknown";
1177
+ messagesDetail += `- **${channel}** (user: ${msg.user || "unknown"}): ${msg.text?.slice(0, 200) || "(no text)"}\n`;
1178
+ }
1137
1179
 
1138
- return prompt;
1180
+ const result = await resolveTemplateAsync("task.trigger.channel_activity", {
1181
+ message_count: trigger.count || msgs.length,
1182
+ messages_detail: messagesDetail,
1183
+ });
1184
+ return result.text;
1139
1185
  }
1140
1186
 
1141
1187
  default:
@@ -1306,6 +1352,17 @@ async function spawnProviderProcess(
1306
1352
  saveProviderSessionId(opts.apiUrl, opts.apiKey, realTaskId, event.sessionId).catch(
1307
1353
  (err) => console.warn(`[runner] Failed to save session ID: ${err}`),
1308
1354
  );
1355
+ } else {
1356
+ // Pool task: save provider session ID on active session so it can be
1357
+ // propagated to the real task when the agent claims one
1358
+ saveProviderSessionIdOnActiveSession(
1359
+ opts.apiUrl,
1360
+ opts.apiKey,
1361
+ effectiveTaskId,
1362
+ event.sessionId,
1363
+ ).catch((err) =>
1364
+ console.warn(`[runner] Failed to save provider session on active session: ${err}`),
1365
+ );
1309
1366
  }
1310
1367
  break;
1311
1368
  case "tool_start": {
@@ -1486,6 +1543,7 @@ async function checkCompletedProcesses(
1486
1543
  taskId: string;
1487
1544
  result: ProviderResult;
1488
1545
  triggerType?: string;
1546
+ cursorUpdates?: Array<{ channelId: string; ts: string }>;
1489
1547
  }> = [];
1490
1548
 
1491
1549
  for (const [taskId, task] of state.activeTasks) {
@@ -1498,12 +1556,13 @@ async function checkCompletedProcesses(
1498
1556
  taskId,
1499
1557
  result: task.result,
1500
1558
  triggerType: task.triggerType,
1559
+ cursorUpdates: task.cursorUpdates,
1501
1560
  });
1502
1561
  }
1503
1562
  }
1504
1563
 
1505
1564
  // Remove completed tasks from the map and ensure they're marked as finished
1506
- for (const { taskId, result } of completedTasks) {
1565
+ for (const { taskId, result, cursorUpdates } of completedTasks) {
1507
1566
  state.activeTasks.delete(taskId);
1508
1567
 
1509
1568
  if (apiConfig) {
@@ -1519,6 +1578,25 @@ async function checkCompletedProcesses(
1519
1578
  console.log(`[${role}] Detected error for task ${taskId.slice(0, 8)}: ${failureReason}`);
1520
1579
  }
1521
1580
  await ensureTaskFinished(apiConfig, role, taskId, result.exitCode, failureReason);
1581
+
1582
+ // Commit channel activity cursors after successful processing
1583
+ // If the task failed, cursors stay uncommitted so messages are re-seen on next poll
1584
+ if (cursorUpdates && cursorUpdates.length > 0 && result.exitCode === 0) {
1585
+ try {
1586
+ const headers: Record<string, string> = { "Content-Type": "application/json" };
1587
+ if (apiConfig.apiKey) headers.Authorization = `Bearer ${apiConfig.apiKey}`;
1588
+ await fetch(`${apiConfig.apiUrl}/api/channel-activity/commit-cursors`, {
1589
+ method: "POST",
1590
+ headers,
1591
+ body: JSON.stringify({ cursorUpdates }),
1592
+ });
1593
+ console.log(
1594
+ `[${role}] Committed ${cursorUpdates.length} channel activity cursor(s) for task ${taskId.slice(0, 8)}`,
1595
+ );
1596
+ } catch (err) {
1597
+ console.warn(`[${role}] Failed to commit channel activity cursors: ${err}`);
1598
+ }
1599
+ }
1522
1600
  }
1523
1601
  }
1524
1602
  }
@@ -1605,6 +1683,11 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1605
1683
  const apiUrl = process.env.MCP_BASE_URL || `http://localhost:${process.env.PORT || "3013"}`;
1606
1684
  const swarmUrl = process.env.SWARM_URL || "localhost";
1607
1685
 
1686
+ // Configure HTTP-based template resolution (workers resolve via API, not local DB)
1687
+ if (process.env.API_KEY) {
1688
+ configureHttpResolver(apiUrl, process.env.API_KEY);
1689
+ }
1690
+
1608
1691
  let capabilities = config.capabilities;
1609
1692
 
1610
1693
  // Agent identity fields — populated after registration by fetching full profile
@@ -1615,12 +1698,13 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1615
1698
  let agentClaudeMd: string | undefined;
1616
1699
  let agentProfileName: string | undefined;
1617
1700
  let agentDescription: string | undefined;
1701
+ let agentSkillsSummary: { name: string; description: string }[] | undefined;
1618
1702
 
1619
1703
  // Per-task repo context — set when processing a task with githubRepo
1620
1704
  let currentRepoContext: BasePromptArgs["repoContext"] | undefined;
1621
1705
 
1622
1706
  // Generate base prompt (identity fields injected after profile fetch below)
1623
- const buildSystemPrompt = () => {
1707
+ const buildSystemPrompt = async () => {
1624
1708
  return getBasePrompt({
1625
1709
  role,
1626
1710
  agentId,
@@ -1633,10 +1717,11 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1633
1717
  toolsMd: agentToolsMd,
1634
1718
  claudeMd: agentClaudeMd,
1635
1719
  repoContext: currentRepoContext,
1720
+ skillsSummary: agentSkillsSummary,
1636
1721
  });
1637
1722
  };
1638
1723
 
1639
- let basePrompt = buildSystemPrompt();
1724
+ let basePrompt = await buildSystemPrompt();
1640
1725
 
1641
1726
  // Resolve additional system prompt: CLI flag > env var
1642
1727
  let additionalSystemPrompt: string | undefined;
@@ -1860,8 +1945,36 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1860
1945
  }
1861
1946
  }
1862
1947
 
1948
+ // Fetch installed skills for system prompt
1949
+ try {
1950
+ const skillsResp = await fetch(`${apiUrl}/api/agents/${agentId}/skills`, {
1951
+ headers: {
1952
+ Authorization: `Bearer ${apiKey}`,
1953
+ "X-Agent-ID": agentId,
1954
+ },
1955
+ });
1956
+ if (skillsResp.ok) {
1957
+ const skillsData = (await skillsResp.json()) as {
1958
+ skills: {
1959
+ name: string;
1960
+ description: string;
1961
+ isActive: boolean;
1962
+ isEnabled: boolean;
1963
+ }[];
1964
+ };
1965
+ agentSkillsSummary = skillsData.skills
1966
+ .filter((s) => s.isActive && s.isEnabled)
1967
+ .map((s) => ({ name: s.name, description: s.description }));
1968
+ if (agentSkillsSummary.length > 0) {
1969
+ console.log(`[${role}] Loaded ${agentSkillsSummary.length} skills for system prompt`);
1970
+ }
1971
+ }
1972
+ } catch {
1973
+ // Non-fatal — skills are optional
1974
+ }
1975
+
1863
1976
  // Rebuild system prompt with identity
1864
- basePrompt = buildSystemPrompt();
1977
+ basePrompt = await buildSystemPrompt();
1865
1978
  resolvedSystemPrompt = additionalSystemPrompt
1866
1979
  ? `${basePrompt}\n\n${additionalSystemPrompt}`
1867
1980
  : basePrompt;
@@ -1928,6 +2041,37 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1928
2041
  }
1929
2042
  }
1930
2043
 
2044
+ // ========== Sync skills to filesystem ==========
2045
+ try {
2046
+ console.log(`[${role}] Syncing skills to filesystem...`);
2047
+ const syncHeaders: Record<string, string> = {
2048
+ "Content-Type": "application/json",
2049
+ "X-Agent-ID": agentId,
2050
+ };
2051
+ if (apiKey) syncHeaders.Authorization = `Bearer ${apiKey}`;
2052
+ const syncRes = await fetch(`${swarmUrl}/api/skills/sync-filesystem`, {
2053
+ method: "POST",
2054
+ headers: syncHeaders,
2055
+ });
2056
+ if (syncRes.ok) {
2057
+ const syncResult = (await syncRes.json()) as {
2058
+ synced: number;
2059
+ removed: number;
2060
+ errors: string[];
2061
+ };
2062
+ console.log(
2063
+ `[${role}] Skills synced: ${syncResult.synced} written, ${syncResult.removed} removed`,
2064
+ );
2065
+ if (syncResult.errors.length > 0) {
2066
+ console.warn(`[${role}] Skill sync errors: ${syncResult.errors.join(", ")}`);
2067
+ }
2068
+ } else {
2069
+ console.warn(`[${role}] Skill sync failed: HTTP ${syncRes.status}`);
2070
+ }
2071
+ } catch (err) {
2072
+ console.warn(`[${role}] Skill sync failed: ${(err as Error).message}`);
2073
+ }
2074
+
1931
2075
  // ========== Resume paused tasks with PRIORITY ==========
1932
2076
  // Check for paused tasks from previous shutdown and resume them before normal polling
1933
2077
  try {
@@ -1966,7 +2110,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
1966
2110
  }
1967
2111
 
1968
2112
  // Build prompt with resume context + memory injection
1969
- let resumePrompt = buildResumePrompt(task, adapter.formatCommand.bind(adapter));
2113
+ let resumePrompt = await buildResumePrompt(task, adapter.formatCommand.bind(adapter));
1970
2114
 
1971
2115
  // Inject relevant memories for resumed tasks
1972
2116
  const resumeMemoryContext = await fetchRelevantMemories(
@@ -2048,32 +2192,46 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2048
2192
  }
2049
2193
  }
2050
2194
 
2051
- const runningTask = await spawnProviderProcess(
2052
- adapter,
2053
- {
2054
- prompt: resumePrompt,
2055
- logFile,
2056
- systemPrompt: resolvedSystemPrompt,
2057
- additionalArgs: resumeAdditionalArgs,
2058
- role,
2059
- apiUrl,
2060
- apiKey,
2061
- agentId,
2062
- runnerSessionId: sessionId,
2063
- iteration,
2064
- taskId: task.id,
2065
- model: (task as { model?: string }).model,
2066
- cwd: resumeCwd,
2067
- },
2068
- logDir,
2069
- isYolo,
2070
- );
2195
+ // Per-task runner session ID so session logs are scoped to this task
2196
+ const resumeRunnerSessionId = crypto.randomUUID();
2197
+
2198
+ let runningTask: RunningTask;
2199
+ try {
2200
+ runningTask = await spawnProviderProcess(
2201
+ adapter,
2202
+ {
2203
+ prompt: resumePrompt,
2204
+ logFile,
2205
+ systemPrompt: resolvedSystemPrompt,
2206
+ additionalArgs: resumeAdditionalArgs,
2207
+ role,
2208
+ apiUrl,
2209
+ apiKey,
2210
+ agentId,
2211
+ runnerSessionId: resumeRunnerSessionId,
2212
+ iteration,
2213
+ taskId: task.id,
2214
+ model: (task as { model?: string }).model,
2215
+ cwd: resumeCwd,
2216
+ },
2217
+ logDir,
2218
+ isYolo,
2219
+ );
2220
+ } catch (spawnErr) {
2221
+ const errMsg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
2222
+ console.error(
2223
+ `[${role}] Failed to spawn process for resumed task ${task.id.slice(0, 8)}: ${errMsg}`,
2224
+ );
2225
+ await ensureTaskFinished(apiConfig, role, task.id, 1, `Spawn failed: ${errMsg}`);
2226
+ continue;
2227
+ }
2071
2228
 
2072
2229
  state.activeTasks.set(task.id, runningTask);
2073
2230
  registerActiveSession(apiConfig, {
2074
2231
  taskId: task.id,
2075
2232
  triggerType: "task_resumed",
2076
2233
  taskDescription: task.task?.slice(0, 200),
2234
+ runnerSessionId: resumeRunnerSessionId,
2077
2235
  });
2078
2236
  console.log(
2079
2237
  `[${role}] Resumed task ${task.id.slice(0, 8)} (${state.activeTasks.size}/${state.maxConcurrent} active)`,
@@ -2151,7 +2309,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2151
2309
  console.log(`[${role}] Trigger received: ${trigger.type}`);
2152
2310
 
2153
2311
  // Build prompt based on trigger
2154
- let triggerPrompt = buildPromptForTrigger(
2312
+ let triggerPrompt = await buildPromptForTrigger(
2155
2313
  trigger,
2156
2314
  prompt,
2157
2315
  adapter.formatCommand.bind(adapter),
@@ -2294,7 +2452,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2294
2452
  }
2295
2453
 
2296
2454
  // Rebuild system prompt with per-task repo context
2297
- const taskBasePrompt = buildSystemPrompt();
2455
+ const taskBasePrompt = await buildSystemPrompt();
2298
2456
  const taskSystemPrompt =
2299
2457
  (additionalSystemPrompt
2300
2458
  ? `${taskBasePrompt}\n\n${additionalSystemPrompt}`
@@ -2323,31 +2481,60 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2323
2481
  };
2324
2482
  await Bun.write(logFile, `${JSON.stringify(metadata)}\n`);
2325
2483
 
2484
+ // Per-task runner session ID so session logs are scoped to this task
2485
+ const taskRunnerSessionId = crypto.randomUUID();
2486
+
2326
2487
  // Spawn without blocking (await to set up session, but process runs async)
2327
- const runningTask = await spawnProviderProcess(
2328
- adapter,
2329
- {
2330
- prompt: triggerPrompt,
2331
- logFile,
2332
- systemPrompt: taskSystemPrompt,
2333
- additionalArgs: effectiveAdditionalArgs,
2334
- role,
2335
- apiUrl,
2336
- apiKey,
2337
- agentId,
2338
- runnerSessionId: sessionId,
2339
- iteration,
2340
- taskId: trigger.taskId,
2341
- model: taskModel,
2342
- cwd: effectiveCwd,
2343
- },
2344
- logDir,
2345
- isYolo,
2346
- );
2488
+ let runningTask: RunningTask;
2489
+ try {
2490
+ runningTask = await spawnProviderProcess(
2491
+ adapter,
2492
+ {
2493
+ prompt: triggerPrompt,
2494
+ logFile,
2495
+ systemPrompt: taskSystemPrompt,
2496
+ additionalArgs: effectiveAdditionalArgs,
2497
+ role,
2498
+ apiUrl,
2499
+ apiKey,
2500
+ agentId,
2501
+ runnerSessionId: taskRunnerSessionId,
2502
+ iteration,
2503
+ taskId: trigger.taskId,
2504
+ model: taskModel,
2505
+ cwd: effectiveCwd,
2506
+ },
2507
+ logDir,
2508
+ isYolo,
2509
+ );
2510
+ } catch (spawnErr) {
2511
+ const errMsg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
2512
+ console.error(
2513
+ `[${role}] Failed to spawn process for task ${trigger.taskId?.slice(0, 8) || "unknown"}: ${errMsg}`,
2514
+ );
2515
+ if (trigger.taskId) {
2516
+ await ensureTaskFinished(
2517
+ apiConfig,
2518
+ role,
2519
+ trigger.taskId,
2520
+ 1,
2521
+ `Spawn failed: ${errMsg}`,
2522
+ );
2523
+ }
2524
+ continue;
2525
+ }
2347
2526
 
2348
2527
  // Attach trigger metadata for logging
2349
2528
  runningTask.triggerType = trigger.type;
2350
2529
 
2530
+ // Attach deferred cursor updates for channel_activity triggers
2531
+ if (trigger.type === "channel_activity" && trigger.cursorUpdates) {
2532
+ runningTask.cursorUpdates = trigger.cursorUpdates as Array<{
2533
+ channelId: string;
2534
+ ts: string;
2535
+ }>;
2536
+ }
2537
+
2351
2538
  state.activeTasks.set(runningTask.taskId, runningTask);
2352
2539
 
2353
2540
  // Register active session for concurrency awareness
@@ -2359,6 +2546,7 @@ export async function runAgent(config: RunnerConfig, opts: RunnerOptions) {
2359
2546
  taskId: runningTask.taskId,
2360
2547
  triggerType: trigger.type,
2361
2548
  taskDescription: taskDesc,
2549
+ runnerSessionId: taskRunnerSessionId,
2362
2550
  });
2363
2551
 
2364
2552
  console.log(