@swarmclawai/swarmclaw 0.8.4 → 0.8.7

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 (394) hide show
  1. package/README.md +9 -9
  2. package/bin/swarmclaw.js +5 -1
  3. package/bin/worker-cmd.js +73 -0
  4. package/package.json +2 -1
  5. package/src/app/api/agents/[id]/route.ts +17 -7
  6. package/src/app/api/agents/route.ts +21 -8
  7. package/src/app/api/approvals/route.test.ts +6 -6
  8. package/src/app/api/approvals/route.ts +2 -1
  9. package/src/app/api/auth/route.ts +2 -3
  10. package/src/app/api/chatrooms/[id]/chat/route.test.ts +299 -0
  11. package/src/app/api/chatrooms/[id]/chat/route.ts +3 -2
  12. package/src/app/api/chatrooms/[id]/route.ts +7 -6
  13. package/src/app/api/chats/[id]/chat/route.test.ts +496 -0
  14. package/src/app/api/chats/[id]/chat/route.ts +7 -3
  15. package/src/app/api/chats/[id]/clear/route.ts +9 -9
  16. package/src/app/api/chats/[id]/devserver/route.ts +2 -1
  17. package/src/app/api/chats/[id]/edit-resend/route.ts +3 -4
  18. package/src/app/api/chats/[id]/fork/route.ts +3 -5
  19. package/src/app/api/chats/[id]/restore/route.ts +6 -7
  20. package/src/app/api/chats/[id]/retry/route.ts +3 -4
  21. package/src/app/api/chats/[id]/route.ts +61 -62
  22. package/src/app/api/chats/route.ts +7 -1
  23. package/src/app/api/connectors/[id]/route.ts +7 -8
  24. package/src/app/api/connectors/route.ts +5 -4
  25. package/src/app/api/eval/run/route.ts +2 -1
  26. package/src/app/api/eval/suite/route.ts +2 -1
  27. package/src/app/api/external-agents/route.test.ts +1 -1
  28. package/src/app/api/external-agents/route.ts +2 -2
  29. package/src/app/api/files/serve/route.ts +1 -1
  30. package/src/app/api/gateways/[id]/route.ts +7 -5
  31. package/src/app/api/gateways/route.ts +1 -1
  32. package/src/app/api/knowledge/upload/route.ts +1 -1
  33. package/src/app/api/logs/route.ts +5 -7
  34. package/src/app/api/memory-images/[filename]/route.ts +2 -3
  35. package/src/app/api/openclaw/agent-files/route.ts +4 -3
  36. package/src/app/api/openclaw/approvals/route.ts +3 -4
  37. package/src/app/api/openclaw/config-sync/route.ts +3 -2
  38. package/src/app/api/openclaw/cron/route.ts +3 -2
  39. package/src/app/api/openclaw/dotenv-keys/route.ts +2 -1
  40. package/src/app/api/openclaw/exec-config/route.ts +3 -2
  41. package/src/app/api/openclaw/gateway/route.ts +5 -4
  42. package/src/app/api/openclaw/history/route.ts +3 -2
  43. package/src/app/api/openclaw/media/route.ts +2 -1
  44. package/src/app/api/openclaw/permissions/route.ts +3 -2
  45. package/src/app/api/openclaw/sandbox-env/route.ts +3 -2
  46. package/src/app/api/openclaw/skills/install/route.ts +2 -1
  47. package/src/app/api/openclaw/skills/remove/route.ts +2 -1
  48. package/src/app/api/openclaw/skills/route.ts +3 -2
  49. package/src/app/api/orchestrator/run/route.ts +5 -14
  50. package/src/app/api/perf/route.ts +43 -0
  51. package/src/app/api/plugins/dependencies/route.ts +2 -1
  52. package/src/app/api/plugins/install/route.ts +2 -1
  53. package/src/app/api/plugins/marketplace/route.ts +3 -2
  54. package/src/app/api/plugins/settings/route.ts +2 -1
  55. package/src/app/api/preview-server/route.ts +11 -10
  56. package/src/app/api/projects/[id]/route.ts +1 -1
  57. package/src/app/api/schedules/[id]/route.test.ts +128 -0
  58. package/src/app/api/schedules/[id]/route.ts +43 -43
  59. package/src/app/api/schedules/[id]/run/route.ts +11 -62
  60. package/src/app/api/schedules/route.ts +21 -87
  61. package/src/app/api/settings/route.ts +2 -0
  62. package/src/app/api/setup/doctor/route.ts +9 -8
  63. package/src/app/api/tasks/[id]/approve/route.ts +33 -30
  64. package/src/app/api/tasks/[id]/route.ts +12 -35
  65. package/src/app/api/tasks/import/github/route.ts +2 -1
  66. package/src/app/api/tasks/route.ts +79 -91
  67. package/src/app/api/wallets/[id]/approve/route.ts +2 -1
  68. package/src/app/api/wallets/[id]/route.ts +13 -19
  69. package/src/app/api/wallets/[id]/send/route.ts +2 -1
  70. package/src/app/api/wallets/route.ts +2 -1
  71. package/src/app/api/webhooks/[id]/route.ts +2 -1
  72. package/src/app/api/webhooks/route.test.ts +3 -1
  73. package/src/app/page.tsx +23 -331
  74. package/src/cli/index.js +19 -0
  75. package/src/cli/index.ts +38 -7
  76. package/src/cli/spec.js +9 -0
  77. package/src/components/activity/activity-feed.tsx +7 -4
  78. package/src/components/agents/agent-card.tsx +32 -6
  79. package/src/components/agents/agent-chat-list.tsx +55 -22
  80. package/src/components/agents/agent-files-editor.tsx +3 -2
  81. package/src/components/agents/agent-sheet.tsx +123 -22
  82. package/src/components/agents/inspector-panel.tsx +1 -1
  83. package/src/components/agents/openclaw-skills-panel.tsx +2 -1
  84. package/src/components/agents/trash-list.tsx +1 -1
  85. package/src/components/auth/access-key-gate.tsx +8 -2
  86. package/src/components/auth/setup-wizard.tsx +10 -9
  87. package/src/components/auth/user-picker.tsx +3 -2
  88. package/src/components/chat/chat-area.tsx +20 -1
  89. package/src/components/chat/chat-card.tsx +18 -3
  90. package/src/components/chat/chat-header.tsx +24 -4
  91. package/src/components/chat/chat-list.tsx +2 -11
  92. package/src/components/chat/heartbeat-history-panel.tsx +2 -1
  93. package/src/components/chat/message-bubble.tsx +45 -6
  94. package/src/components/chat/message-list.tsx +280 -145
  95. package/src/components/chat/streaming-bubble.tsx +217 -60
  96. package/src/components/chat/swarm-panel.test.ts +274 -0
  97. package/src/components/chat/swarm-panel.tsx +410 -0
  98. package/src/components/chat/swarm-status-card.tsx +346 -0
  99. package/src/components/chat/tool-call-bubble.tsx +48 -23
  100. package/src/components/chatrooms/chatroom-list.tsx +8 -5
  101. package/src/components/chatrooms/chatroom-message.tsx +10 -7
  102. package/src/components/chatrooms/chatroom-view.tsx +12 -9
  103. package/src/components/connectors/connector-health.tsx +6 -4
  104. package/src/components/connectors/connector-list.tsx +16 -11
  105. package/src/components/connectors/connector-sheet.tsx +12 -6
  106. package/src/components/home/home-view.tsx +38 -24
  107. package/src/components/input/chat-input.tsx +10 -1
  108. package/src/components/layout/app-layout.tsx +2 -38
  109. package/src/components/layout/sheet-layer.tsx +50 -0
  110. package/src/components/mcp-servers/mcp-server-list.tsx +37 -5
  111. package/src/components/mcp-servers/mcp-server-sheet.tsx +12 -2
  112. package/src/components/plugins/plugin-list.tsx +8 -4
  113. package/src/components/plugins/plugin-sheet.tsx +2 -1
  114. package/src/components/providers/provider-list.tsx +3 -2
  115. package/src/components/providers/provider-sheet.tsx +2 -1
  116. package/src/components/runs/run-list.tsx +11 -7
  117. package/src/components/schedules/schedule-card.tsx +5 -3
  118. package/src/components/shared/agent-switch-dialog.tsx +1 -1
  119. package/src/components/shared/attachment-chip.tsx +19 -3
  120. package/src/components/shared/notification-center.tsx +6 -3
  121. package/src/components/shared/settings/plugin-manager.tsx +3 -2
  122. package/src/components/shared/settings/section-embedding.tsx +2 -1
  123. package/src/components/shared/settings/section-orchestrator.tsx +2 -1
  124. package/src/components/shared/settings/section-user-preferences.tsx +107 -0
  125. package/src/components/shared/settings/settings-page.tsx +13 -9
  126. package/src/components/skills/clawhub-browser.tsx +15 -4
  127. package/src/components/skills/skill-list.tsx +15 -4
  128. package/src/components/tasks/approvals-panel.tsx +2 -1
  129. package/src/components/tasks/task-board.tsx +35 -37
  130. package/src/components/tasks/task-sheet.tsx +4 -3
  131. package/src/components/ui/full-screen-loader.tsx +164 -0
  132. package/src/components/wallets/wallet-approval-dialog.tsx +2 -1
  133. package/src/components/wallets/wallet-panel.tsx +6 -5
  134. package/src/components/wallets/wallet-section.tsx +3 -2
  135. package/src/components/webhooks/webhook-list.tsx +4 -5
  136. package/src/components/webhooks/webhook-sheet.tsx +6 -6
  137. package/src/hooks/use-app-bootstrap.ts +202 -0
  138. package/src/hooks/use-mounted-ref.ts +14 -0
  139. package/src/hooks/use-now.ts +31 -0
  140. package/src/hooks/use-openclaw-gateway.ts +2 -1
  141. package/src/instrumentation.ts +20 -8
  142. package/src/lib/agent-default-tools.test.ts +52 -0
  143. package/src/lib/agent-default-tools.ts +40 -0
  144. package/src/lib/api-client.test.ts +21 -0
  145. package/src/lib/api-client.ts +6 -11
  146. package/src/lib/canvas-content.test.ts +360 -0
  147. package/src/lib/chat-streaming-state.test.ts +49 -2
  148. package/src/lib/chat-streaming-state.ts +26 -10
  149. package/src/lib/fetch-timeout.test.ts +54 -0
  150. package/src/lib/fetch-timeout.ts +60 -3
  151. package/src/lib/live-tool-events.test.ts +77 -0
  152. package/src/lib/live-tool-events.ts +73 -0
  153. package/src/lib/local-observability.test.ts +2 -2
  154. package/src/lib/openclaw-endpoint.test.ts +1 -1
  155. package/src/lib/providers/anthropic.ts +12 -16
  156. package/src/lib/providers/index.ts +4 -2
  157. package/src/lib/providers/ollama.ts +9 -6
  158. package/src/lib/providers/openai.ts +11 -14
  159. package/src/lib/runtime-env.test.ts +8 -8
  160. package/src/lib/schedule-dedupe-advanced.test.ts +2 -2
  161. package/src/lib/schedule-dedupe.test.ts +1 -1
  162. package/src/lib/schedule-dedupe.ts +3 -2
  163. package/src/lib/server/agent-thread-session.test.ts +6 -6
  164. package/src/lib/server/agent-thread-session.ts +6 -9
  165. package/src/lib/server/alert-dispatch.ts +2 -1
  166. package/src/lib/server/api-routes.test.ts +6 -6
  167. package/src/lib/server/approval-connector-notify.test.ts +4 -4
  168. package/src/lib/server/approvals-auto-approve.test.ts +29 -29
  169. package/src/lib/server/approvals.test.ts +317 -0
  170. package/src/lib/server/approvals.ts +5 -4
  171. package/src/lib/server/autonomy-runtime.test.ts +11 -11
  172. package/src/lib/server/browser-state.ts +2 -2
  173. package/src/lib/server/capability-router.test.ts +1 -1
  174. package/src/lib/server/capability-router.ts +3 -2
  175. package/src/lib/server/chat-execution-advanced.test.ts +15 -2
  176. package/src/lib/server/chat-execution-connector-delivery.ts +67 -0
  177. package/src/lib/server/chat-execution-disabled.test.ts +3 -3
  178. package/src/lib/server/chat-execution-eval-history.test.ts +3 -3
  179. package/src/lib/server/chat-execution-heartbeat.test.ts +42 -1
  180. package/src/lib/server/chat-execution-session-sync.test.ts +119 -0
  181. package/src/lib/server/chat-execution-tool-events.ts +116 -0
  182. package/src/lib/server/chat-execution-utils.test.ts +479 -0
  183. package/src/lib/server/chat-execution-utils.ts +533 -0
  184. package/src/lib/server/chat-execution.ts +153 -748
  185. package/src/lib/server/chat-streaming-utils.ts +174 -0
  186. package/src/lib/server/chat-turn-tool-routing.ts +310 -0
  187. package/src/lib/server/chatroom-session-persistence.test.ts +2 -2
  188. package/src/lib/server/clawhub-client.ts +2 -1
  189. package/src/lib/server/collection-helpers.test.ts +92 -0
  190. package/src/lib/server/collection-helpers.ts +25 -3
  191. package/src/lib/server/connectors/access.ts +146 -0
  192. package/src/lib/server/connectors/bluebubbles.test.ts +1 -1
  193. package/src/lib/server/connectors/bluebubbles.ts +4 -4
  194. package/src/lib/server/connectors/commands.ts +367 -0
  195. package/src/lib/server/connectors/connector-routing.test.ts +4 -4
  196. package/src/lib/server/connectors/delivery.ts +142 -0
  197. package/src/lib/server/connectors/discord.ts +37 -40
  198. package/src/lib/server/connectors/email.ts +11 -10
  199. package/src/lib/server/connectors/googlechat.ts +4 -4
  200. package/src/lib/server/connectors/inbound-audio-transcription.ts +2 -1
  201. package/src/lib/server/connectors/ingress-delivery.ts +23 -0
  202. package/src/lib/server/connectors/manager-roundtrip.test.ts +300 -0
  203. package/src/lib/server/connectors/manager.test.ts +352 -77
  204. package/src/lib/server/connectors/manager.ts +134 -673
  205. package/src/lib/server/connectors/matrix.ts +4 -4
  206. package/src/lib/server/connectors/message-sentinel.ts +7 -0
  207. package/src/lib/server/connectors/openclaw.test.ts +1 -1
  208. package/src/lib/server/connectors/openclaw.ts +8 -10
  209. package/src/lib/server/connectors/outbox.test.ts +192 -0
  210. package/src/lib/server/connectors/outbox.ts +369 -0
  211. package/src/lib/server/connectors/pairing.test.ts +18 -1
  212. package/src/lib/server/connectors/pairing.ts +49 -4
  213. package/src/lib/server/connectors/policy.ts +9 -3
  214. package/src/lib/server/connectors/reconnect-state.ts +71 -0
  215. package/src/lib/server/connectors/response-media.ts +256 -0
  216. package/src/lib/server/connectors/runtime-state.ts +67 -0
  217. package/src/lib/server/connectors/session.test.ts +357 -0
  218. package/src/lib/server/connectors/session.ts +422 -0
  219. package/src/lib/server/connectors/signal.ts +7 -7
  220. package/src/lib/server/connectors/slack.ts +43 -43
  221. package/src/lib/server/connectors/teams.ts +4 -4
  222. package/src/lib/server/connectors/telegram.ts +37 -43
  223. package/src/lib/server/connectors/types.ts +31 -1
  224. package/src/lib/server/connectors/whatsapp.test.ts +108 -0
  225. package/src/lib/server/connectors/whatsapp.ts +106 -34
  226. package/src/lib/server/context-manager.test.ts +409 -0
  227. package/src/lib/server/cost.test.ts +1 -1
  228. package/src/lib/server/daemon-policy.ts +78 -0
  229. package/src/lib/server/daemon-state-connectors.test.ts +167 -0
  230. package/src/lib/server/daemon-state.test.ts +283 -55
  231. package/src/lib/server/daemon-state.ts +106 -109
  232. package/src/lib/server/data-dir.test.ts +5 -5
  233. package/src/lib/server/data-dir.ts +4 -0
  234. package/src/lib/server/delegation-jobs-advanced.test.ts +1 -1
  235. package/src/lib/server/delegation-jobs.test.ts +87 -0
  236. package/src/lib/server/delegation-jobs.ts +42 -48
  237. package/src/lib/server/devserver-launch.ts +1 -1
  238. package/src/lib/server/document-utils.ts +7 -9
  239. package/src/lib/server/elevenlabs.ts +2 -1
  240. package/src/lib/server/embeddings.test.ts +105 -0
  241. package/src/lib/server/ethereum.ts +3 -2
  242. package/src/lib/server/eval/agent-regression.ts +3 -2
  243. package/src/lib/server/eval/runner.ts +2 -1
  244. package/src/lib/server/eval/scorer.ts +2 -1
  245. package/src/lib/server/evm-swap.ts +2 -1
  246. package/src/lib/server/gateway/protocol.test.ts +1 -1
  247. package/src/lib/server/guardian.ts +2 -1
  248. package/src/lib/server/heartbeat-blocked-suppression.test.ts +151 -0
  249. package/src/lib/server/heartbeat-service-timer.test.ts +6 -6
  250. package/src/lib/server/heartbeat-service.test.ts +406 -0
  251. package/src/lib/server/heartbeat-service.ts +54 -7
  252. package/src/lib/server/heartbeat-wake.test.ts +19 -0
  253. package/src/lib/server/heartbeat-wake.ts +17 -16
  254. package/src/lib/server/integrity-monitor.test.ts +149 -0
  255. package/src/lib/server/json-utils.ts +22 -0
  256. package/src/lib/server/knowledge-db.test.ts +13 -13
  257. package/src/lib/server/link-understanding.ts +2 -1
  258. package/src/lib/server/llm-response-cache.test.ts +1 -1
  259. package/src/lib/server/main-agent-loop-advanced.test.ts +65 -3
  260. package/src/lib/server/main-agent-loop.test.ts +6 -6
  261. package/src/lib/server/main-agent-loop.ts +21 -7
  262. package/src/lib/server/mcp-client.test.ts +1 -1
  263. package/src/lib/server/mcp-conformance.test.ts +1 -1
  264. package/src/lib/server/mcp-conformance.ts +3 -2
  265. package/src/lib/server/memory-consolidation.ts +2 -1
  266. package/src/lib/server/memory-db.test.ts +485 -0
  267. package/src/lib/server/memory-db.ts +39 -26
  268. package/src/lib/server/memory-graph.test.ts +2 -2
  269. package/src/lib/server/memory-policy.test.ts +7 -7
  270. package/src/lib/server/memory-retrieval.test.ts +1 -1
  271. package/src/lib/server/openclaw-config-sync.ts +2 -1
  272. package/src/lib/server/openclaw-deploy.test.ts +1 -1
  273. package/src/lib/server/openclaw-deploy.ts +8 -12
  274. package/src/lib/server/openclaw-exec-config.ts +2 -1
  275. package/src/lib/server/openclaw-gateway.ts +6 -7
  276. package/src/lib/server/openclaw-skills-normalize.ts +2 -1
  277. package/src/lib/server/openclaw-sync.ts +7 -5
  278. package/src/lib/server/orchestrator-lg-structure.test.ts +17 -0
  279. package/src/lib/server/orchestrator-lg.ts +199 -327
  280. package/src/lib/server/path-utils.ts +31 -0
  281. package/src/lib/server/perf.ts +161 -0
  282. package/src/lib/server/plugins-approval-guidance.ts +115 -0
  283. package/src/lib/server/plugins.test.ts +1 -1
  284. package/src/lib/server/plugins.ts +22 -132
  285. package/src/lib/server/process-manager.ts +5 -8
  286. package/src/lib/server/provider-health.test.ts +137 -0
  287. package/src/lib/server/provider-health.ts +3 -3
  288. package/src/lib/server/provider-model-discovery.ts +3 -12
  289. package/src/lib/server/queue-followups.test.ts +9 -9
  290. package/src/lib/server/queue-reconcile.test.ts +2 -2
  291. package/src/lib/server/queue-recovery.test.ts +269 -0
  292. package/src/lib/server/queue.test.ts +570 -0
  293. package/src/lib/server/queue.ts +62 -455
  294. package/src/lib/server/resolve-image.ts +30 -0
  295. package/src/lib/server/runtime-settings.test.ts +4 -4
  296. package/src/lib/server/runtime-storage-write-paths.test.ts +60 -0
  297. package/src/lib/server/schedule-normalization.test.ts +279 -0
  298. package/src/lib/server/schedule-service.ts +263 -0
  299. package/src/lib/server/scheduler.ts +17 -74
  300. package/src/lib/server/session-mailbox.test.ts +191 -0
  301. package/src/lib/server/session-run-manager.test.ts +640 -0
  302. package/src/lib/server/session-run-manager.ts +59 -15
  303. package/src/lib/server/session-tools/autonomy-tools.test.ts +20 -20
  304. package/src/lib/server/session-tools/calendar.ts +2 -1
  305. package/src/lib/server/session-tools/canvas.ts +2 -1
  306. package/src/lib/server/session-tools/chatroom.ts +2 -1
  307. package/src/lib/server/session-tools/connector.ts +26 -28
  308. package/src/lib/server/session-tools/context-mgmt.ts +3 -2
  309. package/src/lib/server/session-tools/crawl.ts +4 -3
  310. package/src/lib/server/session-tools/crud.ts +105 -324
  311. package/src/lib/server/session-tools/delegate-fallback.test.ts +9 -9
  312. package/src/lib/server/session-tools/delegate.ts +6 -8
  313. package/src/lib/server/session-tools/discovery-approvals.test.ts +15 -15
  314. package/src/lib/server/session-tools/discovery.ts +4 -3
  315. package/src/lib/server/session-tools/document.ts +2 -1
  316. package/src/lib/server/session-tools/email.ts +2 -1
  317. package/src/lib/server/session-tools/extract.ts +2 -1
  318. package/src/lib/server/session-tools/file.ts +4 -3
  319. package/src/lib/server/session-tools/http.ts +2 -1
  320. package/src/lib/server/session-tools/human-loop.ts +2 -1
  321. package/src/lib/server/session-tools/image-gen.ts +4 -3
  322. package/src/lib/server/session-tools/index.ts +26 -30
  323. package/src/lib/server/session-tools/mailbox.ts +2 -1
  324. package/src/lib/server/session-tools/manage-connectors.test.ts +4 -4
  325. package/src/lib/server/session-tools/manage-schedules.test.ts +12 -12
  326. package/src/lib/server/session-tools/manage-tasks-advanced.test.ts +5 -5
  327. package/src/lib/server/session-tools/manage-tasks.test.ts +2 -2
  328. package/src/lib/server/session-tools/monitor.ts +2 -1
  329. package/src/lib/server/session-tools/platform.ts +2 -1
  330. package/src/lib/server/session-tools/plugin-creator.ts +2 -1
  331. package/src/lib/server/session-tools/replicate.ts +3 -2
  332. package/src/lib/server/session-tools/session-tools-wiring.test.ts +6 -6
  333. package/src/lib/server/session-tools/shell.ts +4 -9
  334. package/src/lib/server/session-tools/subagent.ts +322 -170
  335. package/src/lib/server/session-tools/table.ts +6 -5
  336. package/src/lib/server/session-tools/wallet-tool.test.ts +3 -3
  337. package/src/lib/server/session-tools/wallet.ts +7 -6
  338. package/src/lib/server/session-tools/web-browser-config.test.ts +1 -0
  339. package/src/lib/server/session-tools/web-utils.ts +317 -0
  340. package/src/lib/server/session-tools/web.ts +62 -328
  341. package/src/lib/server/skill-prompt-budget.test.ts +1 -1
  342. package/src/lib/server/skills-normalize.ts +2 -1
  343. package/src/lib/server/storage-item-access.test.ts +302 -0
  344. package/src/lib/server/storage.ts +366 -314
  345. package/src/lib/server/stream-agent-chat.test.ts +82 -3
  346. package/src/lib/server/stream-agent-chat.ts +146 -510
  347. package/src/lib/server/stream-continuation.ts +412 -0
  348. package/src/lib/server/subagent-lineage.test.ts +647 -0
  349. package/src/lib/server/subagent-lineage.ts +435 -0
  350. package/src/lib/server/subagent-runtime.test.ts +484 -0
  351. package/src/lib/server/subagent-runtime.ts +419 -0
  352. package/src/lib/server/subagent-swarm.test.ts +391 -0
  353. package/src/lib/server/subagent-swarm.ts +564 -0
  354. package/src/lib/server/system-events.ts +3 -3
  355. package/src/lib/server/task-followups.test.ts +491 -0
  356. package/src/lib/server/task-followups.ts +391 -0
  357. package/src/lib/server/task-lifecycle.test.ts +205 -0
  358. package/src/lib/server/task-lifecycle.ts +200 -0
  359. package/src/lib/server/task-quality-gate.test.ts +1 -1
  360. package/src/lib/server/task-resume.ts +208 -0
  361. package/src/lib/server/task-service.test.ts +108 -0
  362. package/src/lib/server/task-service.ts +264 -0
  363. package/src/lib/server/task-validation.test.ts +1 -1
  364. package/src/lib/server/test-utils/run-with-temp-data-dir.ts +42 -0
  365. package/src/lib/server/tool-capability-policy.test.ts +2 -2
  366. package/src/lib/server/tool-capability-policy.ts +3 -2
  367. package/src/lib/server/tool-planning.ts +2 -1
  368. package/src/lib/server/tool-retry.ts +2 -3
  369. package/src/lib/server/wake-dispatcher.test.ts +303 -0
  370. package/src/lib/server/wake-dispatcher.ts +318 -0
  371. package/src/lib/server/wake-mode.test.ts +161 -0
  372. package/src/lib/server/wake-mode.ts +174 -0
  373. package/src/lib/server/wallet-service.ts +8 -9
  374. package/src/lib/server/watch-jobs.ts +2 -1
  375. package/src/lib/server/workspace-context.ts +2 -2
  376. package/src/lib/shared-utils.test.ts +142 -0
  377. package/src/lib/shared-utils.ts +62 -0
  378. package/src/lib/tool-event-summary.ts +2 -1
  379. package/src/lib/view-routes.test.ts +100 -0
  380. package/src/lib/wallet.test.ts +322 -6
  381. package/src/proxy.test.ts +4 -4
  382. package/src/proxy.ts +2 -3
  383. package/src/stores/set-if-changed.ts +40 -0
  384. package/src/stores/slices/agent-slice.ts +111 -0
  385. package/src/stores/slices/auth-slice.ts +25 -0
  386. package/src/stores/slices/data-slice.ts +301 -0
  387. package/src/stores/slices/index.ts +7 -0
  388. package/src/stores/slices/session-slice.ts +112 -0
  389. package/src/stores/slices/task-slice.ts +63 -0
  390. package/src/stores/slices/ui-slice.ts +192 -0
  391. package/src/stores/use-app-store.ts +17 -822
  392. package/src/stores/use-approval-store.ts +2 -1
  393. package/src/stores/use-chat-store.ts +8 -1
  394. package/src/types/index.ts +10 -0
@@ -0,0 +1,435 @@
1
+ /**
2
+ * Subagent Lineage & Lifecycle Tracker
3
+ *
4
+ * Tracks parent → child relationships between subagent sessions and manages
5
+ * lifecycle state transitions. The lifecycle state lives directly on the
6
+ * lineage node (single source of truth), eliminating the need for a separate
7
+ * state machine registry.
8
+ *
9
+ * Lineage nodes are stored in-memory (globalThis-scoped for HMR safety).
10
+ */
11
+
12
+ import { genId } from '@/lib/id'
13
+ import { hmrSingleton } from '@/lib/shared-utils'
14
+ import { notify } from './ws-hub'
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Lifecycle States & Events
18
+ // ---------------------------------------------------------------------------
19
+
20
+ export type SubagentState =
21
+ | 'initializing' // Being set up (session creation, lineage registration)
22
+ | 'ready' // Session created, queued for execution
23
+ | 'running' // Actively executing
24
+ | 'waiting' // Paused while a child subagent completes
25
+ | 'completed' // Finished successfully
26
+ | 'failed' // Finished with error
27
+ | 'cancelled' // Cancelled by parent or user
28
+ | 'timed_out' // Exceeded time limit
29
+
30
+ export type SubagentEvent =
31
+ | 'READY' // Setup complete, queued
32
+ | 'START' // Begin execution
33
+ | 'SPAWN_CHILD' // Spawned a child subagent, waiting
34
+ | 'CHILD_DONE' // Child subagent completed, resume
35
+ | 'COMPLETE' // Execution finished successfully
36
+ | 'FAIL' // Execution finished with error
37
+ | 'CANCEL' // Cancelled externally
38
+ | 'TIMEOUT' // Time limit exceeded
39
+
40
+ const TRANSITIONS: Record<SubagentState, Partial<Record<SubagentEvent, SubagentState>>> = {
41
+ initializing: { READY: 'ready', FAIL: 'failed', CANCEL: 'cancelled' },
42
+ ready: { START: 'running', FAIL: 'failed', CANCEL: 'cancelled' },
43
+ running: { SPAWN_CHILD: 'waiting', COMPLETE: 'completed', FAIL: 'failed', CANCEL: 'cancelled', TIMEOUT: 'timed_out' },
44
+ waiting: { CHILD_DONE: 'running', COMPLETE: 'completed', FAIL: 'failed', CANCEL: 'cancelled', TIMEOUT: 'timed_out' },
45
+ completed: {},
46
+ failed: {},
47
+ cancelled: {},
48
+ timed_out: {},
49
+ }
50
+
51
+ export function isTerminalState(state: SubagentState): boolean {
52
+ return state === 'completed' || state === 'failed' || state === 'cancelled' || state === 'timed_out'
53
+ }
54
+
55
+ /** Resolve next state for a (state, event) pair. Returns undefined if invalid. */
56
+ function resolveTransition(state: SubagentState, event: SubagentEvent): SubagentState | undefined {
57
+ return TRANSITIONS[state]?.[event]
58
+ }
59
+
60
+ /**
61
+ * Check if a transition is valid without performing it.
62
+ */
63
+ export function canTransition(nodeOrState: string | SubagentState, event: SubagentEvent): boolean {
64
+ // If it looks like a lineage node ID, look it up
65
+ const state: SubagentState | undefined =
66
+ (nodeOrState in TRANSITIONS)
67
+ ? nodeOrState as SubagentState
68
+ : store.get(nodeOrState)?.status
69
+ if (!state) return false
70
+ return resolveTransition(state, event) !== undefined
71
+ }
72
+
73
+ /**
74
+ * Get valid events from a state (for tests / introspection).
75
+ */
76
+ export function validEvents(state: SubagentState): SubagentEvent[] {
77
+ return Object.keys(TRANSITIONS[state] ?? {}) as SubagentEvent[]
78
+ }
79
+
80
+ // ---------------------------------------------------------------------------
81
+ // Types
82
+ // ---------------------------------------------------------------------------
83
+
84
+ export interface LineageNode {
85
+ /** Unique lineage node ID */
86
+ id: string
87
+ /** Session ID of this subagent */
88
+ sessionId: string
89
+ /** Agent ID executing in this session */
90
+ agentId: string
91
+ /** Agent display name */
92
+ agentName: string
93
+ /** Parent lineage node ID (null for root agents) */
94
+ parentId: string | null
95
+ /** Parent session ID (null for root agents) */
96
+ parentSessionId: string | null
97
+ /** Delegation job ID that spawned this subagent */
98
+ jobId: string | null
99
+ /** Nesting depth (0 = root, 1 = first-level subagent, etc.) */
100
+ depth: number
101
+ /** Task/message that was delegated */
102
+ task: string
103
+ /** Working directory */
104
+ cwd: string | null
105
+ /** Timestamps */
106
+ createdAt: number
107
+ completedAt: number | null
108
+ /** Lifecycle state — single source of truth for execution status */
109
+ status: SubagentState
110
+ /** Result summary (truncated) */
111
+ resultPreview: string | null
112
+ /** Error message if failed */
113
+ error: string | null
114
+ }
115
+
116
+ export interface LineageTree {
117
+ node: LineageNode
118
+ children: LineageTree[]
119
+ }
120
+
121
+ export interface LineageQuery {
122
+ sessionId?: string
123
+ agentId?: string
124
+ parentId?: string | null
125
+ status?: SubagentState
126
+ minDepth?: number
127
+ maxDepth?: number
128
+ }
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // Storage (globalThis-scoped, HMR-safe)
132
+ // ---------------------------------------------------------------------------
133
+
134
+ const store = hmrSingleton('__swarmclaw_subagent_lineage__', () => new Map<string, LineageNode>())
135
+
136
+ // Session → lineage node index for fast lookup
137
+ const sessionIndex = hmrSingleton('__swarmclaw_lineage_session_idx__', () => new Map<string, string>())
138
+
139
+ // Debounced notification — collapses rapid-fire updates into one per microtask
140
+ let notifyPending = false
141
+ function notifyLineageChanged() {
142
+ if (notifyPending) return
143
+ notifyPending = true
144
+ queueMicrotask(() => {
145
+ notifyPending = false
146
+ notify('delegation_jobs')
147
+ })
148
+ }
149
+
150
+ // ---------------------------------------------------------------------------
151
+ // Lifecycle Transitions
152
+ // ---------------------------------------------------------------------------
153
+
154
+ /**
155
+ * Transition a lineage node's lifecycle state. Returns the new state,
156
+ * or null if the transition is invalid or the node doesn't exist.
157
+ */
158
+ export function transitionState(nodeId: string, event: SubagentEvent): SubagentState | null {
159
+ const node = store.get(nodeId)
160
+ if (!node) return null
161
+ const next = resolveTransition(node.status, event)
162
+ if (!next) return null
163
+ store.set(nodeId, { ...node, status: next })
164
+ notifyLineageChanged()
165
+ return next
166
+ }
167
+
168
+ // ---------------------------------------------------------------------------
169
+ // Core CRUD
170
+ // ---------------------------------------------------------------------------
171
+
172
+ export interface CreateLineageNodeInput {
173
+ sessionId: string
174
+ agentId: string
175
+ agentName: string
176
+ parentSessionId?: string | null
177
+ jobId?: string | null
178
+ task: string
179
+ cwd?: string | null
180
+ }
181
+
182
+ export function createLineageNode(input: CreateLineageNodeInput): LineageNode {
183
+ const parentNodeId = input.parentSessionId
184
+ ? sessionIndex.get(input.parentSessionId) ?? null
185
+ : null
186
+ const parentNode = parentNodeId ? store.get(parentNodeId) ?? null : null
187
+ const depth = parentNode ? parentNode.depth + 1 : 0
188
+
189
+ const node: LineageNode = {
190
+ id: genId(10),
191
+ sessionId: input.sessionId,
192
+ agentId: input.agentId,
193
+ agentName: input.agentName,
194
+ parentId: parentNodeId,
195
+ parentSessionId: input.parentSessionId ?? null,
196
+ jobId: input.jobId ?? null,
197
+ depth,
198
+ task: input.task,
199
+ cwd: input.cwd ?? null,
200
+ createdAt: Date.now(),
201
+ completedAt: null,
202
+ status: 'initializing',
203
+ resultPreview: null,
204
+ error: null,
205
+ }
206
+
207
+ store.set(node.id, node)
208
+ sessionIndex.set(node.sessionId, node.id)
209
+ notifyLineageChanged()
210
+ return node
211
+ }
212
+
213
+ export function getLineageNode(id: string): LineageNode | null {
214
+ return store.get(id) ?? null
215
+ }
216
+
217
+ export function getLineageNodeBySession(sessionId: string): LineageNode | null {
218
+ const nodeId = sessionIndex.get(sessionId)
219
+ return nodeId ? store.get(nodeId) ?? null : null
220
+ }
221
+
222
+ export function updateLineageNode(
223
+ id: string,
224
+ patch: Partial<Pick<LineageNode, 'completedAt' | 'resultPreview' | 'error'>>,
225
+ ): LineageNode | null {
226
+ const current = store.get(id)
227
+ if (!current) return null
228
+ const updated = { ...current, ...patch }
229
+ store.set(id, updated)
230
+ notifyLineageChanged()
231
+ return updated
232
+ }
233
+
234
+ export function completeLineageNode(id: string, resultPreview: string | null): LineageNode | null {
235
+ const node = store.get(id)
236
+ if (!node) return null
237
+ if (isTerminalState(node.status)) return node
238
+ const next = resolveTransition(node.status, 'COMPLETE')
239
+ if (!next) return null
240
+ const updated = { ...node, status: next, completedAt: Date.now(), resultPreview }
241
+ store.set(id, updated)
242
+ notifyLineageChanged()
243
+ return updated
244
+ }
245
+
246
+ export function failLineageNode(id: string, error: string): LineageNode | null {
247
+ const node = store.get(id)
248
+ if (!node) return null
249
+ if (isTerminalState(node.status)) return node
250
+ const next = resolveTransition(node.status, 'FAIL')
251
+ if (!next) return null
252
+ const updated = { ...node, status: next, completedAt: Date.now(), error }
253
+ store.set(id, updated)
254
+ notifyLineageChanged()
255
+ return updated
256
+ }
257
+
258
+ export function cancelLineageNode(id: string): LineageNode | null {
259
+ const node = store.get(id)
260
+ if (!node) return null
261
+ if (isTerminalState(node.status)) return node
262
+ const next = resolveTransition(node.status, 'CANCEL')
263
+ if (!next) return null
264
+ const updated = { ...node, status: next, completedAt: Date.now() }
265
+ store.set(id, updated)
266
+ notifyLineageChanged()
267
+ return updated
268
+ }
269
+
270
+ // ---------------------------------------------------------------------------
271
+ // Queries
272
+ // ---------------------------------------------------------------------------
273
+
274
+ export function listLineageNodes(query?: LineageQuery): LineageNode[] {
275
+ let nodes = Array.from(store.values())
276
+
277
+ if (query?.sessionId) {
278
+ nodes = nodes.filter((n) => n.sessionId === query.sessionId)
279
+ }
280
+ if (query?.agentId) {
281
+ nodes = nodes.filter((n) => n.agentId === query.agentId)
282
+ }
283
+ if (query?.parentId !== undefined) {
284
+ nodes = nodes.filter((n) => n.parentId === query.parentId)
285
+ }
286
+ if (query?.status) {
287
+ nodes = nodes.filter((n) => n.status === query.status)
288
+ }
289
+ if (query?.minDepth !== undefined) {
290
+ nodes = nodes.filter((n) => n.depth >= query.minDepth!)
291
+ }
292
+ if (query?.maxDepth !== undefined) {
293
+ nodes = nodes.filter((n) => n.depth <= query.maxDepth!)
294
+ }
295
+
296
+ return nodes.sort((a, b) => a.createdAt - b.createdAt)
297
+ }
298
+
299
+ /** Get all ancestors of a node, from immediate parent to root */
300
+ export function getAncestors(nodeId: string): LineageNode[] {
301
+ const ancestors: LineageNode[] = []
302
+ let currentId: string | null = nodeId
303
+ const visited = new Set<string>()
304
+
305
+ while (currentId && !visited.has(currentId)) {
306
+ visited.add(currentId)
307
+ const node = store.get(currentId)
308
+ if (!node?.parentId) break
309
+ const parent = store.get(node.parentId)
310
+ if (!parent) break
311
+ ancestors.push(parent)
312
+ currentId = parent.id
313
+ }
314
+
315
+ return ancestors
316
+ }
317
+
318
+ /** Get direct children of a node */
319
+ export function getChildren(nodeId: string): LineageNode[] {
320
+ return Array.from(store.values())
321
+ .filter((n) => n.parentId === nodeId)
322
+ .sort((a, b) => a.createdAt - b.createdAt)
323
+ }
324
+
325
+ /** Get all descendants of a node (breadth-first) */
326
+ export function getDescendants(nodeId: string): LineageNode[] {
327
+ const descendants: LineageNode[] = []
328
+ const queue = [nodeId]
329
+ const visited = new Set<string>()
330
+
331
+ while (queue.length > 0) {
332
+ const currentId = queue.shift()!
333
+ if (visited.has(currentId)) continue
334
+ visited.add(currentId)
335
+
336
+ const children = getChildren(currentId)
337
+ for (const child of children) {
338
+ descendants.push(child)
339
+ queue.push(child.id)
340
+ }
341
+ }
342
+
343
+ return descendants
344
+ }
345
+
346
+ /** Get siblings (other children of the same parent) */
347
+ export function getSiblings(nodeId: string): LineageNode[] {
348
+ const node = store.get(nodeId)
349
+ if (!node?.parentId) return []
350
+ return getChildren(node.parentId).filter((n) => n.id !== nodeId)
351
+ }
352
+
353
+ /** Build a full lineage tree starting from a node */
354
+ export function buildLineageTree(nodeId: string): LineageTree | null {
355
+ const node = store.get(nodeId)
356
+ if (!node) return null
357
+
358
+ const children = getChildren(nodeId)
359
+ .map((child) => buildLineageTree(child.id))
360
+ .filter((tree): tree is LineageTree => tree !== null)
361
+
362
+ return { node, children }
363
+ }
364
+
365
+ /** Find all root nodes (nodes with no parent) */
366
+ export function getRootNodes(): LineageNode[] {
367
+ return Array.from(store.values())
368
+ .filter((n) => n.parentId === null)
369
+ .sort((a, b) => a.createdAt - b.createdAt)
370
+ }
371
+
372
+ /** Get the root ancestor of a node */
373
+ export function getRootAncestor(nodeId: string): LineageNode | null {
374
+ const ancestors = getAncestors(nodeId)
375
+ return ancestors.length > 0 ? ancestors[ancestors.length - 1] : store.get(nodeId) ?? null
376
+ }
377
+
378
+ /** Get the depth of the deepest descendant */
379
+ export function getMaxDepth(nodeId: string): number {
380
+ const descendants = getDescendants(nodeId)
381
+ if (descendants.length === 0) {
382
+ const node = store.get(nodeId)
383
+ return node?.depth ?? 0
384
+ }
385
+ return Math.max(...descendants.map((d) => d.depth))
386
+ }
387
+
388
+ /** Cancel a node and all its active descendants */
389
+ export function cancelSubtree(nodeId: string): number {
390
+ let cancelled = 0
391
+ const node = store.get(nodeId)
392
+ if (node && !isTerminalState(node.status)) {
393
+ cancelLineageNode(nodeId)
394
+ cancelled++
395
+ }
396
+ for (const desc of getDescendants(nodeId)) {
397
+ if (!isTerminalState(desc.status)) {
398
+ cancelLineageNode(desc.id)
399
+ cancelled++
400
+ }
401
+ }
402
+ return cancelled
403
+ }
404
+
405
+ // ---------------------------------------------------------------------------
406
+ // Cleanup
407
+ // ---------------------------------------------------------------------------
408
+
409
+ /**
410
+ * Remove terminal lineage nodes older than maxAgeMs.
411
+ * Returns the IDs of removed nodes so callers can clean up related resources.
412
+ */
413
+ export function cleanupTerminalNodes(maxAgeMs = 30 * 60_000): string[] {
414
+ const threshold = Date.now() - maxAgeMs
415
+ const removed: string[] = []
416
+ for (const [id, node] of store.entries()) {
417
+ if (!isTerminalState(node.status)) continue
418
+ if (node.completedAt && node.completedAt < threshold) {
419
+ store.delete(id)
420
+ sessionIndex.delete(node.sessionId)
421
+ removed.push(id)
422
+ }
423
+ }
424
+ return removed
425
+ }
426
+
427
+ // ---------------------------------------------------------------------------
428
+ // Testing utilities
429
+ // ---------------------------------------------------------------------------
430
+
431
+ /** Clear all lineage data (for tests only) */
432
+ export function _clearLineage(): void {
433
+ store.clear()
434
+ sessionIndex.clear()
435
+ }