@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,412 @@
1
+ /**
2
+ * Continuation logic for stream-agent-chat.
3
+ *
4
+ * Determines whether an LLM iteration should continue (and why),
5
+ * builds the appropriate follow-up prompts, and resolves final
6
+ * response text from tool-heavy turns.
7
+ */
8
+ import type { MessageToolEvent } from '@/types'
9
+ import { extractSuggestions } from './suggestions'
10
+
11
+ // ---------------------------------------------------------------------------
12
+ // Types
13
+ // ---------------------------------------------------------------------------
14
+
15
+ export type ContinuationType =
16
+ | 'recursion'
17
+ | 'transient'
18
+ | 'required_tool'
19
+ | 'attachment_followthrough'
20
+ | 'execution_followthrough'
21
+ | 'deliverable_followthrough'
22
+ | 'tool_summary'
23
+ | false
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Message classification helpers
27
+ // ---------------------------------------------------------------------------
28
+
29
+ export function isBroadGoal(text: string): boolean {
30
+ if (text.length < 50) return false
31
+ if (/```/.test(text)) return false
32
+ if (/\/(src|lib|app|pages|components|api)\//.test(text)) return false
33
+ if (/^\s*\d+[.)]\s/m.test(text)) return false
34
+ if (text.length < 80 && text.endsWith('?')) return false
35
+ return true
36
+ }
37
+
38
+ export function looksLikeExternalWalletTask(text: string): boolean {
39
+ const normalized = text.toLowerCase()
40
+ if (!normalized.trim()) return false
41
+ return /\b(wallet|wallet connect|walletconnect|trade|trading|exchange|dex|bridge|swap|deposit|withdraw|onchain|token|gas|hyperliquid|arbitrum|ethereum|solana|base|usdc|eth|sol)\b/.test(normalized)
42
+ }
43
+
44
+ export function looksLikeBoundedExternalExecutionTask(text: string): boolean {
45
+ const normalized = text.toLowerCase()
46
+ if (!looksLikeExternalWalletTask(text)) return false
47
+ return /\b(live|swap|trade|buy|purchase|sell|mint|claim|execute|transact|transaction|approve|broadcast)\b/.test(normalized)
48
+ }
49
+
50
+ export function looksLikeOpenEndedDeliverableTask(text: string): boolean {
51
+ const normalized = text.toLowerCase()
52
+ if (!normalized.trim()) return false
53
+ if (/```|package\.json|tsconfig|\btsx?\b|\bjsx?\b|pytest|vitest|npm run|src\/|components\/|api\//.test(normalized)) return false
54
+ if (/\b(revise|revision|iterate|iteration|draft|deliverable|deliverables|offer|brief|copy|proposal|landing|outreach|plan|strategy|report|memo|document|docs?)\b/.test(normalized)) return true
55
+ if (
56
+ /\b(create|build|generate|make|write|produce)\b/.test(normalized)
57
+ && /\b(save|write|output|export)\b[^.!?\n]{0,60}\b(to|as|in)\b[^.!?\n]{0,40}(\/|~\/|\.\/|\.[a-z]{2,5}\b)/.test(normalized)
58
+ ) {
59
+ return true
60
+ }
61
+ if (
62
+ isBroadGoal(text)
63
+ && /\b(create|build|generate|make|write|research|capture|take|start|produce)\b/.test(normalized)
64
+ && /\b(screenshot|screenshots|image|images|markdown|\.md\b|md\b|md files?|pdf|pdf files?|html|html\s+(?:page|file)|dashboard|site|sites|website|web page|webpage|dev server|dev servers|artifact|artifacts|topic|topics)\b/.test(normalized)
65
+ ) {
66
+ return true
67
+ }
68
+ return isBroadGoal(text) && /(\.md\b|\.txt\b|\.html\b|\.json\b|copy|brief|proposal|plan|report|draft|document|dashboard)/.test(normalized)
69
+ }
70
+
71
+ function looksLikeIncompleteDeliverableResponse(text: string): boolean {
72
+ const trimmed = text.trim()
73
+ if (!trimmed) return true
74
+ if (trimmed.endsWith(':') || trimmed.endsWith('...') || trimmed.endsWith('…')) return true
75
+ const lastChunk = trimmed.slice(-400).toLowerCase()
76
+ return /\b(?:next|now|then|after that|moving on to|proceeding to)\b[^.!?\n]{0,120}\b(?:i(?:'ll| will)|create|build|write|capture|take|start|finish|generate)\b/.test(lastChunk)
77
+ || /\b(?:i(?:'ll| will)|let me)\s+(?:now|next)?\s*(?:create|build|write|capture|take|start|finish|generate|continue)\b/.test(lastChunk)
78
+ }
79
+
80
+ // ---------------------------------------------------------------------------
81
+ // Tool evidence analysis
82
+ // ---------------------------------------------------------------------------
83
+
84
+ export function hasStateChangingWalletEvidence(toolEvents: MessageToolEvent[]): boolean {
85
+ return toolEvents.some((event) => {
86
+ const input = `${event.input || ''}\n${event.output || ''}`
87
+ return event.name === 'wallet_tool' && (
88
+ /"action":"send_transaction"/.test(input)
89
+ || /"action":"send"/.test(input)
90
+ || /"action":"sign_transaction"/.test(input)
91
+ || /"type":"plugin_wallet_action_request"/.test(input)
92
+ || /"type":"plugin_wallet_transfer_request"/.test(input)
93
+ || /"status":"broadcast"/.test(input)
94
+ )
95
+ })
96
+ }
97
+
98
+ export function countExternalExecutionResearchSteps(toolEvents: MessageToolEvent[]): number {
99
+ return toolEvents.filter((event) => {
100
+ if (['http_request', 'web', 'web_search', 'web_fetch', 'browser'].includes(event.name)) return true
101
+ if (event.name !== 'wallet_tool') return false
102
+ return /"action":"(balance|address|transactions|call_contract|encode_contract_call)"/.test(event.input || '')
103
+ }).length
104
+ }
105
+
106
+ export function countDistinctExternalResearchHosts(toolEvents: MessageToolEvent[]): number {
107
+ const hosts = new Set<string>()
108
+ for (const event of toolEvents) {
109
+ const candidates = [event.input || '', event.output || '']
110
+ for (const candidate of candidates) {
111
+ const matches = candidate.match(/https?:\/\/[^"'\\\s)]+/g) || []
112
+ for (const match of matches) {
113
+ try {
114
+ hosts.add(new URL(match).host.toLowerCase())
115
+ } catch {
116
+ // Ignore malformed URLs in model/tool text.
117
+ }
118
+ }
119
+ }
120
+ }
121
+ return hosts.size
122
+ }
123
+
124
+ // ---------------------------------------------------------------------------
125
+ // Continuation decision helpers
126
+ // ---------------------------------------------------------------------------
127
+
128
+ export function shouldForceExternalExecutionFollowthrough(params: {
129
+ userMessage: string
130
+ finalResponse: string
131
+ hasToolCalls: boolean
132
+ toolEvents: MessageToolEvent[]
133
+ }): boolean {
134
+ if (!looksLikeBoundedExternalExecutionTask(params.userMessage)) return false
135
+ if (!params.hasToolCalls || params.toolEvents.length < 4) return false
136
+ if (hasStateChangingWalletEvidence(params.toolEvents)) return false
137
+ const distinctHosts = countDistinctExternalResearchHosts(params.toolEvents)
138
+ const trimmed = params.finalResponse.trim()
139
+ if (!trimmed) return countExternalExecutionResearchSteps(params.toolEvents) >= 4 || distinctHosts >= 3
140
+ if (/\b(last reversible step|exact blocker|safest next action|blocked|cannot|can't|missing capability|no-key route unavailable)\b/i.test(trimmed)) {
141
+ return false
142
+ }
143
+ if (countExternalExecutionResearchSteps(params.toolEvents) < 4 && distinctHosts < 3) return false
144
+ return /(let me|i'll|i will|trying|research|query|check|look|promising|now let me|good -|good,)/i.test(trimmed) || trimmed.length < 500
145
+ }
146
+
147
+ export function shouldForceDeliverableFollowthrough(params: {
148
+ userMessage: string
149
+ finalResponse: string
150
+ hasToolCalls: boolean
151
+ toolEvents: MessageToolEvent[]
152
+ }): boolean {
153
+ if (!looksLikeOpenEndedDeliverableTask(params.userMessage)) return false
154
+ if (!params.hasToolCalls || params.toolEvents.length === 0) return false
155
+ const trimmed = params.finalResponse.trim()
156
+ if (!trimmed) return params.toolEvents.length >= 2
157
+ if (
158
+ /\b(task complete|completed|finished|done|delivered|shared|sent|uploaded|attached)\b/i.test(trimmed)
159
+ && /(?:\/api\/uploads\/|https?:\/\/|`[^`\n]+\.(?:md|pdf|png|jpe?g|webp|gif|html|txt|zip)`)/i.test(trimmed)
160
+ ) {
161
+ return false
162
+ }
163
+ const userNormalized = params.userMessage.toLowerCase()
164
+ if (/\b(save|write|output)\b[^.!?\n]{0,60}\b(to|as)\b[^.!?\n]{0,40}(\/|~\/|\.[a-z]{2,5}\b)/.test(userNormalized)) {
165
+ const usedFileWriteTools = params.toolEvents.some((e) => {
166
+ if (!e.name) return false
167
+ if (['write_file', 'edit_file'].includes(e.name)) return true
168
+ if (e.name === 'shell' || e.name === 'execute_command') return true
169
+ if (e.name === 'files') {
170
+ const input = e.input || ''
171
+ return /"action"\s*:\s*"write"/i.test(input)
172
+ }
173
+ return false
174
+ })
175
+ if (!usedFileWriteTools) return true
176
+ }
177
+ if (looksLikeIncompleteDeliverableResponse(trimmed)) return true
178
+ return trimmed.length < 120 && params.toolEvents.length >= 3
179
+ }
180
+
181
+ // ---------------------------------------------------------------------------
182
+ // Tool evidence rendering (shared with buildForcedExternalServiceSummary)
183
+ // ---------------------------------------------------------------------------
184
+
185
+ export function renderToolEvidence(events: MessageToolEvent[]): string {
186
+ return events
187
+ .slice(-10)
188
+ .map((event, index) => [
189
+ `Tool ${index + 1}: ${event.name}`,
190
+ event.input ? `Input: ${event.input}` : '',
191
+ event.output ? `Output: ${event.output.slice(0, 1200)}` : '',
192
+ ].filter(Boolean).join('\n'))
193
+ .join('\n\n')
194
+ }
195
+
196
+ // ---------------------------------------------------------------------------
197
+ // Continuation prompt builders
198
+ // ---------------------------------------------------------------------------
199
+
200
+ function buildExternalExecutionFollowthroughPrompt(params: {
201
+ userMessage: string
202
+ fullText: string
203
+ toolEvents: MessageToolEvent[]
204
+ }): string {
205
+ return [
206
+ 'You are in a bounded external execution task and have already done enough research.',
207
+ 'Do not restart broad discovery. Do not ask the user for another prompt.',
208
+ 'Do not spend this continuation on more venue shopping. Use the already confirmed route unless one last fetch is strictly required to prepare execution.',
209
+ 'If several venue or aggregator APIs already failed, stop searching for more venues. Either use a direct onchain read path with the available wallet tools, or state the blocker.',
210
+ 'A prose approval request does not count as completion. If the next step is a sign/send/approve action, call the real wallet tool action so the runtime can create the approval request.',
211
+ 'Do not mutate already confirmed token addresses, router addresses, spender addresses, or network identifiers unless newer tool evidence proves the earlier value was wrong.',
212
+ 'Within this continuation, do exactly one of the following:',
213
+ '1. Take the next concrete execution step now using the existing tools and stop at the first approval boundary for a state-changing action.',
214
+ '2. If no safe executable step exists with the current tools, state the exact blocker with evidence.',
215
+ 'A successful continuation ends with one of these outcomes only: an approval request, a broadcast transaction, or a final blocker summary.',
216
+ 'Prefer the route sources and facts already confirmed in the tool evidence below. Do not keep shopping for new venues unless the current options are clearly unusable.',
217
+ 'If the tool evidence already includes enough information to prepare a contract call, approval, quote read, or transaction simulation, do that now instead of making another search or HTTP request.',
218
+ '',
219
+ `Objective:\n${params.userMessage}`,
220
+ '',
221
+ `Current partial response:\n${params.fullText || '(none)'}`,
222
+ '',
223
+ `Recent tool evidence:\n${renderToolEvidence(params.toolEvents) || '(none)'}`,
224
+ ].join('\n')
225
+ }
226
+
227
+ function buildDeliverableFollowthroughPrompt(params: {
228
+ userMessage: string
229
+ fullText: string
230
+ toolEvents: MessageToolEvent[]
231
+ }): string {
232
+ const lines = [
233
+ 'You are in the middle of a multi-step deliverable and stopped after only a partial batch of work.',
234
+ 'Continue from the existing workspace and artifacts. Do not restart from scratch and do not ask the user to restate the request.',
235
+ 'Do not stop after one partial batch. Finish every requested deliverable that is still outstanding before concluding.',
236
+ 'If a requested artifact cannot be produced, say exactly which artifact is missing, what blocked it, and what you already completed.',
237
+ 'Use the existing files, screenshots, and generated outputs first. Inspect them if needed, then complete the remaining work.',
238
+ 'Preserve hard structural constraints from the original request: exact counts stay exact, required titled sections stay present, and source coverage gaps should be filled instead of skipped.',
239
+ 'End with a concise grouped completion summary that lists exact file paths, upload URLs, localhost URLs/ports, and screenshots you produced.',
240
+ ]
241
+
242
+ const userNormalized = params.userMessage.toLowerCase()
243
+ const fileOutputMatch = userNormalized.match(/\b(?:save|write|output|export)\b[^.!?\n]{0,80}\b(?:to|as|at|in)\b[^.!?\n]{0,60}(\/[^\s,'"]+|~\/[^\s,'"]+|\.\/[^\s,'"]+)/i)
244
+ if (fileOutputMatch) {
245
+ const fileToolNames = ['write_file', 'edit_file', 'files', 'shell', 'execute_command']
246
+ const usedFileTools = params.toolEvents.some((e) => e.name && fileToolNames.includes(e.name))
247
+ if (!usedFileTools) {
248
+ lines.push(
249
+ '',
250
+ `CRITICAL: The user asked you to save output to a file path (${fileOutputMatch[1] || 'see objective'}). You have NOT used any file-writing tool yet.`,
251
+ 'You MUST use the `files` or `write_file` tool to write the content to the requested path. Do not just include the content in your text response — actually write the file.',
252
+ )
253
+ }
254
+ }
255
+
256
+ lines.push(
257
+ '',
258
+ `Objective:\n${params.userMessage}`,
259
+ '',
260
+ `Current partial response:\n${params.fullText || '(none)'}`,
261
+ '',
262
+ `Recent tool evidence:\n${renderToolEvidence(params.toolEvents) || '(none)'}`,
263
+ )
264
+ return lines.join('\n')
265
+ }
266
+
267
+ function buildAttachmentFollowthroughPrompt(params: {
268
+ message: string
269
+ fullText: string
270
+ }): string {
271
+ return [
272
+ 'The current thread already includes user attachments as inline context.',
273
+ 'Image attachments are directly visible to you in the message content. Text and PDF attachments are also available inline when present.',
274
+ 'Do not claim that you cannot use images, attachments, or external tools when they are available in this session.',
275
+ 'If the user wants you to look something up from an attachment, first extract the identifier or details from the attachment/history, then use the enabled tools to continue.',
276
+ 'Only state a blocker if the attachment is genuinely unreadable or a needed tool is actually unavailable after a real attempt.',
277
+ '',
278
+ `Original request:\n${params.message}`,
279
+ '',
280
+ `Your previous response:\n${params.fullText || '(none)'}`,
281
+ '',
282
+ 'Now continue and handle the attachment-aware task correctly.',
283
+ ].join('\n')
284
+ }
285
+
286
+ function buildToolSummaryPrompt(params: {
287
+ message: string
288
+ fullText: string
289
+ toolEvents: MessageToolEvent[]
290
+ }): string {
291
+ const toolSummaryLines = params.toolEvents
292
+ .filter((e) => e.output)
293
+ .map((e) => `[${e.name}]: ${(e.output || '').slice(0, 500)}`)
294
+ .slice(0, 6)
295
+ const preambleNote = params.fullText.trim()
296
+ ? `You started with "${params.fullText.trim().slice(0, 100)}..." but did not follow through with actual results.`
297
+ : 'Your tool calls completed but you did not provide a response.'
298
+ return [
299
+ preambleNote,
300
+ 'Here are the tool results:',
301
+ ...toolSummaryLines,
302
+ '',
303
+ `Original request: ${params.message.slice(0, 500)}`,
304
+ '',
305
+ 'Now answer the original request using these tool results. Be concise and direct. Present the findings clearly.',
306
+ ].join('\n')
307
+ }
308
+
309
+ // ---------------------------------------------------------------------------
310
+ // buildContinuationPrompt — unified prompt builder for all continuation types
311
+ // ---------------------------------------------------------------------------
312
+
313
+ /**
314
+ * Returns the human-message prompt for a given continuation type,
315
+ * or `null` for types that don't push a message (e.g. `transient`).
316
+ */
317
+ export function buildContinuationPrompt(params: {
318
+ type: ContinuationType
319
+ message: string
320
+ fullText: string
321
+ toolEvents: MessageToolEvent[]
322
+ requiredToolReminderNames: string[]
323
+ }): string | null {
324
+ switch (params.type) {
325
+ case 'recursion':
326
+ return 'Continue where you left off. Complete the remaining steps of the objective.'
327
+
328
+ case 'required_tool':
329
+ return `You have not yet completed the required explicit tool step(s): ${params.requiredToolReminderNames.join(', ')}. Use those enabled tools now before declaring success. Do not replace ask_human with a plain-text request, do not replace outbound delivery tools with prose, and do not replace screenshot requests with text-only summaries.`
330
+
331
+ case 'attachment_followthrough':
332
+ return buildAttachmentFollowthroughPrompt({
333
+ message: params.message,
334
+ fullText: params.fullText,
335
+ })
336
+
337
+ case 'execution_followthrough':
338
+ return buildExternalExecutionFollowthroughPrompt({
339
+ userMessage: params.message,
340
+ fullText: params.fullText,
341
+ toolEvents: params.toolEvents,
342
+ })
343
+
344
+ case 'deliverable_followthrough':
345
+ return buildDeliverableFollowthroughPrompt({
346
+ userMessage: params.message,
347
+ fullText: params.fullText,
348
+ toolEvents: params.toolEvents,
349
+ })
350
+
351
+ case 'tool_summary':
352
+ return buildToolSummaryPrompt({
353
+ message: params.message,
354
+ fullText: params.fullText,
355
+ toolEvents: params.toolEvents,
356
+ })
357
+
358
+ case 'transient':
359
+ case false:
360
+ return null
361
+ }
362
+ }
363
+
364
+ // ---------------------------------------------------------------------------
365
+ // Response text resolution
366
+ // ---------------------------------------------------------------------------
367
+
368
+ function resolveToolOnlyFinalResponse(toolEvents: MessageToolEvent[] | undefined): string {
369
+ const events = Array.isArray(toolEvents) ? toolEvents : []
370
+ for (let index = events.length - 1; index >= 0; index--) {
371
+ const event = events[index]
372
+ const output = typeof event?.output === 'string'
373
+ ? extractSuggestions(event.output).clean.trim()
374
+ : ''
375
+ if (!output) continue
376
+ if (/^error[:\s]/i.test(output)) continue
377
+ if (output.startsWith('{') || output.startsWith('[')) continue
378
+ return output
379
+ }
380
+ return ''
381
+ }
382
+
383
+ export function resolveFinalStreamResponseText(params: {
384
+ fullText: string
385
+ lastSegment: string
386
+ lastSettledSegment: string
387
+ hasToolCalls: boolean
388
+ toolEvents?: MessageToolEvent[]
389
+ }): string {
390
+ const fullText = params.fullText || ''
391
+ if (!params.hasToolCalls) return fullText
392
+
393
+ const candidates = [
394
+ extractSuggestions(params.lastSegment || '').clean.trim(),
395
+ extractSuggestions(params.lastSettledSegment || '').clean.trim(),
396
+ extractSuggestions(fullText).clean.trim(),
397
+ resolveToolOnlyFinalResponse(params.toolEvents),
398
+ ]
399
+
400
+ return candidates.find((candidate) => candidate.length > 0) || ''
401
+ }
402
+
403
+ export function resolveContinuationAssistantText(params: {
404
+ iterationText: string
405
+ lastSegment: string
406
+ }): string {
407
+ const candidates = [
408
+ extractSuggestions(params.iterationText || '').clean.trim(),
409
+ extractSuggestions(params.lastSegment || '').clean.trim(),
410
+ ]
411
+ return candidates.find((candidate) => candidate.length > 0) || ''
412
+ }