@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
@@ -1,826 +1,21 @@
1
1
  'use client'
2
2
 
3
3
  import { create } from 'zustand'
4
- import type { Sessions, Session, NetworkInfo, Directory, ProviderInfo, Credentials, Agent, Schedule, AppView, BoardTask, AppSettings, OrchestratorSecret, ProviderConfig, Skill, Connector, Webhook, McpServerConfig, PluginMeta, Project, FleetFilter, ActivityEntry, AppNotification, ApprovalRequest, GatewayProfile, ExternalAgentRuntime } from '../types'
5
- import { fetchChat, fetchChats, fetchDirs, fetchProviders, fetchCredentials } from '../lib/chats'
6
- import { fetchAgents } from '../lib/agents'
7
- import { fetchSchedules } from '../lib/schedules'
8
- import { fetchTasks } from '../lib/tasks'
9
- import { findLatestObservablePlatformSession, isLocalhostBrowser } from '../lib/local-observability'
10
- import { api } from '../lib/api-client'
11
- import { safeStorageGet, safeStorageGetJson, safeStorageRemove, safeStorageSet } from '../lib/safe-storage'
12
-
13
- const inflightAgentThreadLoads = new Map<string, Promise<void>>()
14
- const inflightSessionRefreshes = new Map<string, Promise<void>>()
15
-
16
- interface AppState {
17
- currentUser: string | null
18
- _hydrated: boolean
19
- hydrate: () => void
20
- setUser: (user: string | null) => void
21
-
22
- sessions: Sessions
23
- currentSessionId: string | null
24
- loadSessions: () => Promise<void>
25
- refreshSession: (id: string) => Promise<void>
26
- setCurrentSession: (id: string | null) => void
27
- removeSession: (id: string) => void
28
- clearSessions: (ids: string[]) => Promise<void>
29
- togglePinSession: (id: string) => void
30
- updateSessionInStore: (session: Session) => void
31
- forkSession: (sessionId: string, messageIndex: number) => Promise<string | null>
32
-
33
- sidebarOpen: boolean
34
- setSidebarOpen: (open: boolean) => void
35
- toggleSidebar: () => void
36
-
37
- networkInfo: NetworkInfo | null
38
- loadNetworkInfo: () => Promise<void>
39
-
40
- dirs: Directory[]
41
- loadDirs: () => Promise<void>
42
-
43
- providers: ProviderInfo[]
44
- credentials: Credentials
45
- loadProviders: () => Promise<void>
46
- loadCredentials: () => Promise<void>
47
-
48
- settingsOpen: boolean
49
- setSettingsOpen: (open: boolean) => void
50
-
51
- activeView: AppView
52
- setActiveView: (view: AppView) => void
53
-
54
- currentAgentId: string | null
55
- setCurrentAgent: (id: string | null) => Promise<void>
56
-
57
- agents: Record<string, Agent>
58
- loadAgents: () => Promise<void>
59
- togglePinAgent: (id: string) => void
60
-
61
- schedules: Record<string, Schedule>
62
- loadSchedules: () => Promise<void>
63
-
64
- agentSheetOpen: boolean
65
- setAgentSheetOpen: (open: boolean) => void
66
- editingAgentId: string | null
67
- setEditingAgentId: (id: string | null) => void
68
-
69
- scheduleSheetOpen: boolean
70
- setScheduleSheetOpen: (open: boolean) => void
71
- editingScheduleId: string | null
72
- setEditingScheduleId: (id: string | null) => void
73
- scheduleTemplatePrefill: { name: string; taskPrompt: string; scheduleType: 'cron' | 'interval'; cron?: string; intervalMs?: number } | null
74
- setScheduleTemplatePrefill: (prefill: { name: string; taskPrompt: string; scheduleType: 'cron' | 'interval'; cron?: string; intervalMs?: number } | null) => void
75
-
76
- memorySheetOpen: boolean
77
- setMemorySheetOpen: (open: boolean) => void
78
- selectedMemoryId: string | null
79
- setSelectedMemoryId: (id: string | null) => void
80
- memoryRefreshKey: number
81
- triggerMemoryRefresh: () => void
82
- memoryAgentFilter: string | null
83
- setMemoryAgentFilter: (agentId: string | null) => void
84
- memoryTierFilter: 'all' | 'working' | 'durable' | 'archive'
85
- setMemoryTierFilter: (tier: 'all' | 'working' | 'durable' | 'archive') => void
86
- memoryScopeFilter: 'all' | 'global' | 'agent' | 'session' | 'project'
87
- setMemoryScopeFilter: (scope: 'all' | 'global' | 'agent' | 'session' | 'project') => void
88
-
89
- appSettings: AppSettings
90
- loadSettings: () => Promise<void>
91
- updateSettings: (patch: Partial<AppSettings>) => Promise<void>
92
-
93
- secrets: Record<string, OrchestratorSecret>
94
- loadSecrets: () => Promise<void>
95
- secretSheetOpen: boolean
96
- setSecretSheetOpen: (open: boolean) => void
97
- editingSecretId: string | null
98
- setEditingSecretId: (id: string | null) => void
99
-
100
- tasks: Record<string, BoardTask>
101
- loadTasks: (includeArchived?: boolean) => Promise<void>
102
- optimisticUpdateTask: (taskId: string, patch: Partial<BoardTask>) => Promise<boolean>
103
- optimisticDeleteTask: (taskId: string) => Promise<boolean>
104
- showArchivedTasks: boolean
105
- setShowArchivedTasks: (show: boolean) => void
106
- taskSheetOpen: boolean
107
- setTaskSheetOpen: (open: boolean) => void
108
- editingTaskId: string | null
109
- setEditingTaskId: (id: string | null) => void
110
- taskSheetViewOnly: boolean
111
- setTaskSheetViewOnly: (v: boolean) => void
112
-
113
- // Provider configs (custom providers)
114
- providerConfigs: ProviderConfig[]
115
- loadProviderConfigs: () => Promise<void>
116
- providerSheetOpen: boolean
117
- setProviderSheetOpen: (open: boolean) => void
118
- editingProviderId: string | null
119
- setEditingProviderId: (id: string | null) => void
120
-
121
- gatewayProfiles: GatewayProfile[]
122
- loadGatewayProfiles: () => Promise<void>
123
- gatewaySheetOpen: boolean
124
- setGatewaySheetOpen: (open: boolean) => void
125
- editingGatewayId: string | null
126
- setEditingGatewayId: (id: string | null) => void
127
-
128
- // Skills
129
- skills: Record<string, Skill>
130
- loadSkills: () => Promise<void>
131
- skillSheetOpen: boolean
132
- setSkillSheetOpen: (open: boolean) => void
133
- editingSkillId: string | null
134
- setEditingSkillId: (id: string | null) => void
135
-
136
- // Connectors
137
- connectors: Record<string, Connector>
138
- loadConnectors: () => Promise<void>
139
- connectorSheetOpen: boolean
140
- setConnectorSheetOpen: (open: boolean) => void
141
- editingConnectorId: string | null
142
- setEditingConnectorId: (id: string | null) => void
143
-
144
- // Webhooks
145
- webhooks: Record<string, Webhook>
146
- loadWebhooks: () => Promise<void>
147
- webhookSheetOpen: boolean
148
- setWebhookSheetOpen: (open: boolean) => void
149
- editingWebhookId: string | null
150
- setEditingWebhookId: (id: string | null) => void
151
-
152
- // MCP Servers
153
- mcpServers: Record<string, McpServerConfig>
154
- loadMcpServers: () => Promise<void>
155
- mcpServerSheetOpen: boolean
156
- setMcpServerSheetOpen: (open: boolean) => void
157
- editingMcpServerId: string | null
158
- setEditingMcpServerId: (id: string | null) => void
159
-
160
- // Knowledge Base
161
- knowledgeSheetOpen: boolean
162
- setKnowledgeSheetOpen: (open: boolean) => void
163
- editingKnowledgeId: string | null
164
- setEditingKnowledgeId: (id: string | null) => void
165
- knowledgeRefreshKey: number
166
- triggerKnowledgeRefresh: () => void
167
-
168
- // Plugins
169
- plugins: Record<string, PluginMeta>
170
- loadPlugins: () => Promise<void>
171
- pluginSheetOpen: boolean
172
- setPluginSheetOpen: (open: boolean) => void
173
- editingPluginFilename: string | null
174
- setEditingPluginFilename: (filename: string | null) => void
175
-
176
- // Projects
177
- projects: Record<string, Project>
178
- loadProjects: () => Promise<void>
179
- projectSheetOpen: boolean
180
- setProjectSheetOpen: (open: boolean) => void
181
- editingProjectId: string | null
182
- setEditingProjectId: (id: string | null) => void
183
- activeProjectFilter: string | null
184
- setActiveProjectFilter: (id: string | null) => void
185
-
186
- // Agent trash
187
- trashedAgents: Record<string, Agent>
188
- loadTrashedAgents: () => Promise<void>
189
- showTrash: boolean
190
- setShowTrash: (show: boolean) => void
191
-
192
- // Inspector panel
193
- inspectorOpen: boolean
194
- setInspectorOpen: (open: boolean) => void
195
- inspectorTab: 'overview' | 'files' | 'skills' | 'automations' | 'advanced'
196
- setInspectorTab: (tab: 'overview' | 'files' | 'skills' | 'automations' | 'advanced') => void
197
-
198
- // Fleet sidebar filter (F16)
199
- fleetFilter: FleetFilter
200
- setFleetFilter: (filter: FleetFilter) => void
201
-
202
- // Chat list filter
203
- chatFilter: 'all' | 'active' | 'recent'
204
- setChatFilter: (filter: 'all' | 'active' | 'recent') => void
205
-
206
- // Activity / Audit Trail
207
- activityEntries: ActivityEntry[]
208
- loadActivity: (filters?: { entityType?: string; limit?: number }) => Promise<void>
209
-
210
- // Unread tracking (localStorage-backed)
211
- lastReadTimestamps: Record<string, number>
212
- markChatRead: (id: string) => void
213
-
214
- // Approvals
215
- approvals: Record<string, ApprovalRequest>
216
- loadApprovals: () => Promise<void>
217
- submitApprovalDecision: (id: string, approved: boolean) => Promise<void>
218
-
219
- // Notifications
220
- notifications: AppNotification[]
221
- unreadNotificationCount: number
222
- loadNotifications: () => Promise<void>
223
- markNotificationRead: (id: string) => Promise<void>
224
- markAllNotificationsRead: () => Promise<void>
225
- clearReadNotifications: () => Promise<void>
226
-
227
- // Wallets
228
- walletPanelAgentId: string | null
229
- setWalletPanelAgentId: (id: string | null) => void
230
-
231
- externalAgents: ExternalAgentRuntime[]
232
- loadExternalAgents: () => Promise<void>
233
-
234
- }
235
-
236
- export const useAppStore = create<AppState>((set, get) => ({
237
- currentUser: null,
238
- _hydrated: false,
239
- hydrate: () => {
240
- const user = safeStorageGet('sc_user')
241
- const savedAgentId = safeStorageGet('sc_agent')
242
- set({ currentUser: user, currentAgentId: savedAgentId, _hydrated: true })
243
- },
244
- setUser: (user) => {
245
- if (user) safeStorageSet('sc_user', user)
246
- else safeStorageRemove('sc_user')
247
- set({ currentUser: user })
248
- },
249
-
250
- sessions: {},
251
- currentSessionId: null,
252
- loadSessions: async () => {
253
- try {
254
- const sessions = await fetchChats()
255
- const currentSessionId = get().currentSessionId
256
- set({
257
- sessions,
258
- currentSessionId: currentSessionId && sessions[currentSessionId] ? currentSessionId : null,
259
- })
260
- } catch {
261
- // ignore
262
- }
263
- },
264
- refreshSession: async (id) => {
265
- if (!id) return
266
- const existing = inflightSessionRefreshes.get(id)
267
- if (existing) {
268
- await existing
269
- return
270
- }
271
-
272
- const refreshPromise = (async () => {
273
- try {
274
- const session = await fetchChat(id)
275
- const currentSessionId = get().currentSessionId
276
- set({
277
- sessions: { ...get().sessions, [id]: session },
278
- currentSessionId: currentSessionId && currentSessionId === id ? id : currentSessionId,
279
- })
280
- } catch {
281
- // ignore
282
- }
283
- })()
284
-
285
- inflightSessionRefreshes.set(id, refreshPromise)
286
- try {
287
- await refreshPromise
288
- } finally {
289
- if (inflightSessionRefreshes.get(id) === refreshPromise) {
290
- inflightSessionRefreshes.delete(id)
291
- }
292
- }
293
- },
294
- setCurrentSession: (id) => set({ currentSessionId: id }),
295
- removeSession: (id) => {
296
- const sessions = { ...get().sessions }
297
- delete sessions[id]
298
- set({ sessions, currentSessionId: get().currentSessionId === id ? null : get().currentSessionId })
299
- },
300
- clearSessions: async (ids) => {
301
- if (!ids.length) return
302
- await api('DELETE', '/chats', { ids })
303
- const sessions = { ...get().sessions }
304
- for (const id of ids) delete sessions[id]
305
- set({ sessions, currentSessionId: ids.includes(get().currentSessionId!) ? null : get().currentSessionId })
306
- },
307
- togglePinSession: (id) => {
308
- const sessions = { ...get().sessions }
309
- if (sessions[id]) {
310
- sessions[id] = { ...sessions[id], pinned: !sessions[id].pinned }
311
- set({ sessions })
312
- // Persist to server
313
- void api('PUT', `/chats/${id}`, { pinned: sessions[id].pinned })
314
- }
315
- },
316
- updateSessionInStore: (session) => {
317
- set({ sessions: { ...get().sessions, [session.id]: session } })
318
- },
319
- forkSession: async (sessionId, messageIndex) => {
320
- try {
321
- const forked = await api<Session>('POST', `/chats/${sessionId}/fork`, { messageIndex })
322
- if (!forked?.id) return null
323
- await get().loadSessions()
324
- set({ currentSessionId: forked.id })
325
- return forked.id
326
- } catch (err: unknown) {
327
- console.error('Fork failed:', err instanceof Error ? err.message : String(err))
328
- return null
329
- }
330
- },
331
-
332
- sidebarOpen: false,
333
- setSidebarOpen: (open) => set({ sidebarOpen: open }),
334
- toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
335
-
336
- networkInfo: null,
337
- loadNetworkInfo: async () => {
338
- try {
339
- const info = await api<NetworkInfo>('GET', '/ip')
340
- set({ networkInfo: info })
341
- } catch {
342
- // ignore
343
- }
344
- },
345
-
346
- dirs: [],
347
- loadDirs: async () => {
348
- try {
349
- const dirs = await fetchDirs()
350
- set({ dirs })
351
- } catch {
352
- set({ dirs: [] })
353
- }
354
- },
355
-
356
- providers: [],
357
- credentials: {},
358
- loadProviders: async () => {
359
- try {
360
- const providers = await fetchProviders()
361
- set({ providers })
362
- } catch {
363
- // ignore
364
- }
365
- },
366
- loadCredentials: async () => {
367
- try {
368
- const credentials = await fetchCredentials()
369
- set({ credentials })
370
- } catch {
371
- // ignore
372
- }
373
- },
374
-
375
- settingsOpen: false,
376
- setSettingsOpen: (open) => set({ settingsOpen: open }),
377
-
378
- activeView: 'home',
379
- setActiveView: (view) => set({ activeView: view }),
380
-
381
- currentAgentId: null,
382
- setCurrentAgent: async (id) => {
383
- if (!id) {
384
- set({ currentAgentId: null })
385
- safeStorageRemove('sc_agent')
386
- return
387
- }
388
- const currentState = get()
389
- const currentSession = currentState.currentSessionId ? currentState.sessions[currentState.currentSessionId] : null
390
- if (currentState.currentAgentId === id && currentSession?.agentId === id) {
391
- return
392
- }
393
- set({ currentAgentId: id })
394
- safeStorageSet('sc_agent', id)
395
- if (isLocalhostBrowser()) {
396
- const livePlatformSession = findLatestObservablePlatformSession(get().sessions, id)
397
- if (livePlatformSession?.id) {
398
- set({ currentSessionId: livePlatformSession.id })
399
- return
400
- }
401
- }
402
-
403
- const existingLoad = inflightAgentThreadLoads.get(id)
404
- if (existingLoad) {
405
- await existingLoad
406
- return
407
- }
408
-
409
- const loadPromise = (async () => {
410
- try {
411
- const user = get().currentUser || 'default'
412
- const session = await api<Session>('POST', `/agents/${id}/thread`, { user })
413
- if (session?.id) {
414
- const sessions = { ...get().sessions, [session.id]: session }
415
- set({ sessions, currentSessionId: session.id })
416
- }
417
- } catch {
418
- // ignore — thread creation failed
419
- }
420
- })()
421
-
422
- inflightAgentThreadLoads.set(id, loadPromise)
423
- try {
424
- await loadPromise
425
- } finally {
426
- if (inflightAgentThreadLoads.get(id) === loadPromise) {
427
- inflightAgentThreadLoads.delete(id)
428
- }
429
- }
430
- },
431
-
432
- agents: {},
433
- loadAgents: async () => {
434
- try {
435
- const agents = await fetchAgents()
436
- set({ agents })
437
- } catch {
438
- // ignore
439
- }
440
- },
441
- togglePinAgent: (id) => {
442
- const agents = { ...get().agents }
443
- if (agents[id]) {
444
- agents[id] = { ...agents[id], pinned: !agents[id].pinned }
445
- set({ agents })
446
- void api('PUT', `/agents/${id}`, { pinned: agents[id].pinned })
447
- }
448
- },
449
-
450
- schedules: {},
451
- loadSchedules: async () => {
452
- try {
453
- const schedules = await fetchSchedules()
454
- set({ schedules })
455
- } catch {
456
- // ignore
457
- }
458
- },
459
-
460
- agentSheetOpen: false,
461
- setAgentSheetOpen: (open) => set({ agentSheetOpen: open }),
462
- editingAgentId: null,
463
- setEditingAgentId: (id) => set({ editingAgentId: id }),
464
-
465
- scheduleSheetOpen: false,
466
- setScheduleSheetOpen: (open) => set({ scheduleSheetOpen: open }),
467
- editingScheduleId: null,
468
- setEditingScheduleId: (id) => set({ editingScheduleId: id }),
469
- scheduleTemplatePrefill: null,
470
- setScheduleTemplatePrefill: (prefill) => set({ scheduleTemplatePrefill: prefill }),
471
-
472
- memorySheetOpen: false,
473
- setMemorySheetOpen: (open) => set({ memorySheetOpen: open }),
474
- selectedMemoryId: null,
475
- setSelectedMemoryId: (id) => set({ selectedMemoryId: id }),
476
- memoryRefreshKey: 0,
477
- triggerMemoryRefresh: () => set((s) => ({ memoryRefreshKey: s.memoryRefreshKey + 1 })),
478
- memoryAgentFilter: null,
479
- setMemoryAgentFilter: (agentId) => set({ memoryAgentFilter: agentId }),
480
- memoryTierFilter: 'all',
481
- setMemoryTierFilter: (tier) => set({ memoryTierFilter: tier }),
482
- memoryScopeFilter: 'all',
483
- setMemoryScopeFilter: (scope) => set({ memoryScopeFilter: scope }),
484
-
485
- appSettings: {},
486
- loadSettings: async () => {
487
- try {
488
- const settings = await api<AppSettings>('GET', '/settings')
489
- set({ appSettings: settings })
490
- } catch {
491
- // ignore
492
- }
493
- },
494
- updateSettings: async (patch) => {
495
- try {
496
- const settings = await api<AppSettings>('PUT', '/settings', patch)
497
- set({ appSettings: settings })
498
- } catch {
499
- // ignore
500
- }
501
- },
502
-
503
- secrets: {},
504
- loadSecrets: async () => {
505
- try {
506
- const secrets = await api<Record<string, OrchestratorSecret>>('GET', '/secrets')
507
- set({ secrets })
508
- } catch {
509
- // ignore
510
- }
511
- },
512
- secretSheetOpen: false,
513
- setSecretSheetOpen: (open) => set({ secretSheetOpen: open }),
514
- editingSecretId: null,
515
- setEditingSecretId: (id) => set({ editingSecretId: id }),
516
-
517
- tasks: {},
518
- loadTasks: async (includeArchived) => {
519
- try {
520
- const show = includeArchived ?? get().showArchivedTasks
521
- const tasks = await fetchTasks(show)
522
- set({ tasks })
523
- } catch {
524
- // ignore
525
- }
526
- },
527
- optimisticUpdateTask: async (taskId, patch) => {
528
- const prev = get().tasks[taskId]
529
- if (!prev) return false
530
- set({ tasks: { ...get().tasks, [taskId]: { ...prev, ...patch, updatedAt: Date.now() } } })
531
- try {
532
- await api('PUT', `/tasks/${taskId}`, patch)
533
- return true
534
- } catch {
535
- set({ tasks: { ...get().tasks, [taskId]: prev } })
536
- return false
537
- }
538
- },
539
- optimisticDeleteTask: async (taskId) => {
540
- const prev = get().tasks[taskId]
541
- if (!prev) return false
542
- const next = { ...get().tasks }
543
- delete next[taskId]
544
- set({ tasks: next })
545
- try {
546
- await api('DELETE', `/tasks/${taskId}`)
547
- return true
548
- } catch {
549
- set({ tasks: { ...get().tasks, [taskId]: prev } })
550
- return false
551
- }
552
- },
553
- showArchivedTasks: false,
554
- setShowArchivedTasks: (show) => {
555
- set({ showArchivedTasks: show })
556
- get().loadTasks(show)
557
- },
558
- taskSheetOpen: false,
559
- setTaskSheetOpen: (open) => set({ taskSheetOpen: open, ...(open ? {} : { taskSheetViewOnly: false }) }),
560
- editingTaskId: null,
561
- setEditingTaskId: (id) => set({ editingTaskId: id }),
562
- taskSheetViewOnly: false,
563
- setTaskSheetViewOnly: (v) => set({ taskSheetViewOnly: v }),
564
-
565
- // Provider configs (custom providers)
566
- providerConfigs: [],
567
- loadProviderConfigs: async () => {
568
- try {
569
- const configs = await api<ProviderConfig[]>('GET', '/providers/configs')
570
- set({ providerConfigs: configs })
571
- } catch {
572
- // ignore
573
- }
574
- },
575
- providerSheetOpen: false,
576
- setProviderSheetOpen: (open) => set({ providerSheetOpen: open }),
577
- editingProviderId: null,
578
- setEditingProviderId: (id) => set({ editingProviderId: id }),
579
-
580
- gatewayProfiles: [],
581
- loadGatewayProfiles: async () => {
582
- try {
583
- const gatewayProfiles = await api<GatewayProfile[]>('GET', '/gateways')
584
- set({ gatewayProfiles })
585
- } catch {
586
- // ignore
587
- }
588
- },
589
- gatewaySheetOpen: false,
590
- setGatewaySheetOpen: (open) => set({ gatewaySheetOpen: open }),
591
- editingGatewayId: null,
592
- setEditingGatewayId: (id) => set({ editingGatewayId: id }),
593
-
594
- // Skills
595
- skills: {},
596
- loadSkills: async () => {
597
- try {
598
- const skills = await api<Record<string, Skill>>('GET', '/skills')
599
- set({ skills })
600
- } catch {
601
- // ignore
602
- }
603
- },
604
- skillSheetOpen: false,
605
- setSkillSheetOpen: (open) => set({ skillSheetOpen: open }),
606
- editingSkillId: null,
607
- setEditingSkillId: (id) => set({ editingSkillId: id }),
608
-
609
- // Connectors
610
- connectors: {},
611
- loadConnectors: async () => {
612
- try {
613
- const connectors = await api<Record<string, Connector>>('GET', '/connectors')
614
- set({ connectors })
615
- } catch {
616
- // ignore
617
- }
618
- },
619
- connectorSheetOpen: false,
620
- setConnectorSheetOpen: (open) => set({ connectorSheetOpen: open }),
621
- editingConnectorId: null,
622
- setEditingConnectorId: (id) => set({ editingConnectorId: id }),
623
-
624
- // Webhooks
625
- webhooks: {},
626
- loadWebhooks: async () => {
627
- try {
628
- const webhooks = await api<Record<string, Webhook>>('GET', '/webhooks')
629
- set({ webhooks })
630
- } catch {
631
- // ignore
632
- }
633
- },
634
- webhookSheetOpen: false,
635
- setWebhookSheetOpen: (open) => set({ webhookSheetOpen: open }),
636
- editingWebhookId: null,
637
- setEditingWebhookId: (id) => set({ editingWebhookId: id }),
638
-
639
- // MCP Servers
640
- mcpServers: {},
641
- loadMcpServers: async () => {
642
- try {
643
- const mcpServers = await api<Record<string, McpServerConfig>>('GET', '/mcp-servers')
644
- set({ mcpServers })
645
- } catch {
646
- // ignore
647
- }
648
- },
649
- mcpServerSheetOpen: false,
650
- setMcpServerSheetOpen: (open) => set({ mcpServerSheetOpen: open }),
651
- editingMcpServerId: null,
652
- setEditingMcpServerId: (id) => set({ editingMcpServerId: id }),
653
-
654
- // Knowledge Base
655
- knowledgeSheetOpen: false,
656
- setKnowledgeSheetOpen: (open) => set({ knowledgeSheetOpen: open }),
657
- editingKnowledgeId: null,
658
- setEditingKnowledgeId: (id) => set({ editingKnowledgeId: id }),
659
- knowledgeRefreshKey: 0,
660
- triggerKnowledgeRefresh: () => set((s) => ({ knowledgeRefreshKey: s.knowledgeRefreshKey + 1 })),
661
-
662
- // Plugins
663
- plugins: {},
664
- loadPlugins: async () => {
665
- try {
666
- const list = await api<PluginMeta[]>('GET', '/plugins')
667
- const plugins: Record<string, PluginMeta> = {}
668
- for (const p of list) plugins[p.filename] = p
669
- set({ plugins })
670
- } catch {
671
- // ignore
672
- }
673
- },
674
- pluginSheetOpen: false,
675
- setPluginSheetOpen: (open) => set({ pluginSheetOpen: open }),
676
- editingPluginFilename: null,
677
- setEditingPluginFilename: (filename) => set({ editingPluginFilename: filename }),
678
-
679
- // Projects
680
- projects: {},
681
- loadProjects: async () => {
682
- try {
683
- const projects = await api<Record<string, Project>>('GET', '/projects')
684
- set({ projects })
685
- } catch {
686
- // ignore
687
- }
688
- },
689
- projectSheetOpen: false,
690
- setProjectSheetOpen: (open) => set({ projectSheetOpen: open }),
691
- editingProjectId: null,
692
- setEditingProjectId: (id) => set({ editingProjectId: id }),
693
- activeProjectFilter: null,
694
- setActiveProjectFilter: (id) => set({ activeProjectFilter: id }),
695
-
696
- // Agent trash
697
- trashedAgents: {},
698
- loadTrashedAgents: async () => {
699
- try {
700
- const trashedAgents = await api<Record<string, Agent>>('GET', '/agents/trash')
701
- set({ trashedAgents })
702
- } catch {
703
- // ignore
704
- }
705
- },
706
- showTrash: false,
707
- setShowTrash: (show) => set({ showTrash: show }),
708
-
709
- // Inspector panel
710
- inspectorOpen: false,
711
- setInspectorOpen: (open) => set({ inspectorOpen: open }),
712
- inspectorTab: 'overview',
713
- setInspectorTab: (tab) => set({ inspectorTab: tab }),
714
-
715
- // Fleet sidebar filter (persisted to localStorage)
716
- fleetFilter: (safeStorageGet('sc_fleet_filter') as FleetFilter) || 'all',
717
- setFleetFilter: (filter) => { safeStorageSet('sc_fleet_filter', filter); set({ fleetFilter: filter }) },
718
-
719
- // Chat list filter
720
- chatFilter: 'all' as const,
721
- setChatFilter: (filter) => set({ chatFilter: filter }),
722
-
723
- // Activity / Audit Trail
724
- activityEntries: [],
725
- loadActivity: async (filters) => {
726
- try {
727
- const params = new URLSearchParams()
728
- if (filters?.entityType) params.set('entityType', filters.entityType)
729
- if (filters?.limit) params.set('limit', String(filters.limit))
730
- const qs = params.toString()
731
- const entries = await api<ActivityEntry[]>('GET', `/activity${qs ? `?${qs}` : ''}`)
732
- set({ activityEntries: entries })
733
- } catch {
734
- // ignore
735
- }
736
- },
737
-
738
- // Unread tracking
739
- lastReadTimestamps: safeStorageGetJson<Record<string, number>>('sc_last_read', {}),
740
- markChatRead: (id) => {
741
- const ts = { ...get().lastReadTimestamps, [id]: Date.now() }
742
- set({ lastReadTimestamps: ts })
743
- safeStorageSet('sc_last_read', JSON.stringify(ts))
744
- },
745
-
746
- // Approvals
747
- approvals: {},
748
- loadApprovals: async () => {
749
- try {
750
- const list = await api<ApprovalRequest[]>('GET', '/approvals')
751
- const approvals: Record<string, ApprovalRequest> = {}
752
- for (const a of list) approvals[a.id] = a
753
- set({ approvals })
754
- } catch { /* ignore */ }
755
- },
756
- submitApprovalDecision: async (id, approved) => {
757
- try {
758
- await api('POST', '/approvals', { id, approved })
759
- await get().loadApprovals()
760
- } catch { /* ignore */ }
761
- },
762
-
763
- // Notifications
764
- notifications: [],
765
- unreadNotificationCount: 0,
766
- loadNotifications: async () => {
767
- try {
768
- const notifications = await api<AppNotification[]>('GET', '/notifications')
769
- set({
770
- notifications,
771
- unreadNotificationCount: notifications.filter((n) => !n.read).length,
772
- })
773
- } catch {
774
- // ignore
775
- }
776
- },
777
- markNotificationRead: async (id) => {
778
- const notifications = get().notifications.map((n) =>
779
- n.id === id ? { ...n, read: true } : n,
780
- )
781
- set({
782
- notifications,
783
- unreadNotificationCount: notifications.filter((n) => !n.read).length,
784
- })
785
- try {
786
- await api('PUT', `/notifications/${id}`, { read: true })
787
- } catch {
788
- // ignore
789
- }
790
- },
791
- markAllNotificationsRead: async () => {
792
- const notifications = get().notifications.map((n) => ({ ...n, read: true }))
793
- set({ notifications, unreadNotificationCount: 0 })
794
- try {
795
- await Promise.all(
796
- get().notifications.filter((n) => !n.read).map((n) => api('PUT', `/notifications/${n.id}`, { read: true })),
797
- )
798
- } catch {
799
- // ignore
800
- }
801
- },
802
- clearReadNotifications: async () => {
803
- const notifications = get().notifications.filter((n) => !n.read)
804
- set({ notifications, unreadNotificationCount: notifications.length })
805
- try {
806
- await api('DELETE', '/notifications')
807
- } catch {
808
- // ignore
809
- }
810
- },
811
-
812
- // Wallets
813
- walletPanelAgentId: null,
814
- setWalletPanelAgentId: (id) => set({ walletPanelAgentId: id }),
815
-
816
- externalAgents: [],
817
- loadExternalAgents: async () => {
818
- try {
819
- const externalAgents = await api<ExternalAgentRuntime[]>('GET', '/external-agents')
820
- set({ externalAgents })
821
- } catch {
822
- // ignore
823
- }
824
- },
825
-
4
+ import type { AuthSlice, SessionSlice, UiSlice, AgentSlice, TaskSlice, DataSlice } from './slices'
5
+ import { createAuthSlice } from './slices/auth-slice'
6
+ import { createSessionSlice } from './slices/session-slice'
7
+ import { createUiSlice } from './slices/ui-slice'
8
+ import { createAgentSlice } from './slices/agent-slice'
9
+ import { createTaskSlice } from './slices/task-slice'
10
+ import { createDataSlice } from './slices/data-slice'
11
+
12
+ export type AppState = AuthSlice & SessionSlice & UiSlice & AgentSlice & TaskSlice & DataSlice
13
+
14
+ export const useAppStore = create<AppState>()((...a) => ({
15
+ ...createAuthSlice(...a),
16
+ ...createSessionSlice(...a),
17
+ ...createUiSlice(...a),
18
+ ...createAgentSlice(...a),
19
+ ...createTaskSlice(...a),
20
+ ...createDataSlice(...a)
826
21
  }))