@swarmclawai/swarmclaw 1.2.4 → 1.2.5

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 (260) hide show
  1. package/README.md +14 -0
  2. package/bin/daemon-cmd.js +169 -0
  3. package/bin/server-cmd.js +3 -0
  4. package/bin/swarmclaw.js +11 -0
  5. package/package.json +17 -16
  6. package/src/app/api/agents/[id]/clone/route.ts +3 -32
  7. package/src/app/api/agents/[id]/route.ts +6 -158
  8. package/src/app/api/agents/[id]/status/route.ts +2 -3
  9. package/src/app/api/agents/[id]/thread/route.ts +4 -17
  10. package/src/app/api/agents/bulk/route.ts +5 -47
  11. package/src/app/api/agents/route.ts +5 -119
  12. package/src/app/api/agents/trash/route.ts +13 -24
  13. package/src/app/api/auth/route.ts +3 -9
  14. package/src/app/api/autonomy/estop/route.ts +5 -5
  15. package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
  16. package/src/app/api/chatrooms/[id]/route.ts +23 -2
  17. package/src/app/api/chatrooms/route.ts +13 -2
  18. package/src/app/api/chats/[id]/clear/route.ts +2 -13
  19. package/src/app/api/chats/[id]/deploy/route.ts +2 -3
  20. package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
  21. package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
  22. package/src/app/api/chats/[id]/queue/route.ts +17 -64
  23. package/src/app/api/chats/[id]/retry/route.ts +4 -22
  24. package/src/app/api/chats/[id]/route.ts +10 -138
  25. package/src/app/api/chats/heartbeat/route.ts +2 -1
  26. package/src/app/api/chats/migrate-messages/route.ts +7 -0
  27. package/src/app/api/chats/route.ts +13 -134
  28. package/src/app/api/connectors/[id]/access/route.ts +12 -229
  29. package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
  30. package/src/app/api/connectors/[id]/health/route.ts +12 -39
  31. package/src/app/api/connectors/[id]/route.ts +14 -122
  32. package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
  33. package/src/app/api/connectors/doctor/route.ts +1 -1
  34. package/src/app/api/connectors/route.ts +12 -70
  35. package/src/app/api/credentials/[id]/route.ts +2 -4
  36. package/src/app/api/credentials/route.ts +10 -19
  37. package/src/app/api/daemon/health-check/route.ts +3 -4
  38. package/src/app/api/daemon/route.ts +10 -8
  39. package/src/app/api/documents/route.ts +11 -10
  40. package/src/app/api/external-agents/route.ts +3 -3
  41. package/src/app/api/gateways/[id]/health/route.ts +2 -3
  42. package/src/app/api/gateways/[id]/route.ts +7 -122
  43. package/src/app/api/gateways/route.ts +3 -103
  44. package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
  45. package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
  46. package/src/app/api/openclaw/directory/route.ts +2 -2
  47. package/src/app/api/openclaw/history/route.ts +3 -5
  48. package/src/app/api/providers/[id]/route.test.ts +49 -0
  49. package/src/app/api/providers/ollama/route.ts +6 -5
  50. package/src/app/api/schedules/[id]/route.ts +14 -108
  51. package/src/app/api/schedules/[id]/run/route.ts +6 -67
  52. package/src/app/api/schedules/route.ts +9 -51
  53. package/src/app/api/settings/route.ts +4 -3
  54. package/src/app/api/setup/check-provider/route.ts +15 -1
  55. package/src/app/api/setup/openclaw-device/route.ts +2 -2
  56. package/src/app/api/system/status/route.ts +2 -2
  57. package/src/app/api/tasks/[id]/route.ts +16 -202
  58. package/src/app/api/tasks/bulk/route.ts +5 -86
  59. package/src/app/api/tasks/metrics/route.ts +2 -1
  60. package/src/app/api/tasks/route.ts +11 -171
  61. package/src/app/api/upload/route.ts +1 -1
  62. package/src/app/api/uploads/[filename]/route.ts +1 -1
  63. package/src/app/api/uploads/route.ts +1 -1
  64. package/src/app/api/webhooks/[id]/history/route.ts +2 -2
  65. package/src/app/layout.tsx +9 -6
  66. package/src/app/protocols/page.tsx +71 -89
  67. package/src/app/tasks/page.tsx +32 -32
  68. package/src/cli/index.js +1 -0
  69. package/src/cli/spec.js +1 -0
  70. package/src/components/agents/agent-sheet.tsx +5 -5
  71. package/src/components/auth/setup-wizard/index.tsx +4 -4
  72. package/src/components/auth/setup-wizard/step-agents.tsx +1 -1
  73. package/src/components/auth/setup-wizard/step-connect.tsx +1 -1
  74. package/src/components/auth/setup-wizard/utils.ts +1 -1
  75. package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
  76. package/src/components/connectors/connector-list.tsx +26 -40
  77. package/src/components/connectors/connector-sheet.tsx +95 -149
  78. package/src/components/gateways/gateway-sheet.tsx +61 -110
  79. package/src/components/layout/live-query-sync.tsx +121 -0
  80. package/src/components/protocols/structured-session-launcher.tsx +24 -45
  81. package/src/components/providers/app-query-provider.tsx +17 -0
  82. package/src/components/providers/provider-list.tsx +60 -61
  83. package/src/components/providers/provider-sheet.tsx +74 -56
  84. package/src/components/skills/skill-list.tsx +5 -18
  85. package/src/components/skills/skill-sheet.tsx +21 -20
  86. package/src/components/skills/skills-workspace.tsx +48 -87
  87. package/src/components/tasks/task-card.tsx +20 -13
  88. package/src/components/tasks/task-column.tsx +22 -7
  89. package/src/components/tasks/task-list.tsx +8 -11
  90. package/src/components/tasks/task-sheet.tsx +111 -103
  91. package/src/features/agents/queries.ts +20 -0
  92. package/src/features/chatrooms/queries.ts +20 -0
  93. package/src/features/chats/queries.ts +27 -0
  94. package/src/features/connectors/queries.ts +145 -0
  95. package/src/features/credentials/queries.ts +37 -0
  96. package/src/features/extensions/queries.ts +26 -0
  97. package/src/features/external-agents/queries.ts +36 -0
  98. package/src/features/gateways/queries.ts +274 -0
  99. package/src/features/missions/queries.ts +23 -0
  100. package/src/features/projects/queries.ts +20 -0
  101. package/src/features/protocols/queries.ts +149 -0
  102. package/src/features/providers/queries.ts +142 -0
  103. package/src/features/settings/queries.ts +20 -0
  104. package/src/features/skills/queries.ts +182 -0
  105. package/src/features/tasks/queries.ts +189 -0
  106. package/src/hooks/use-ws.ts +3 -2
  107. package/src/lib/app/api-client.ts +2 -2
  108. package/src/lib/query/client.ts +17 -0
  109. package/src/lib/server/agents/agent-runtime-config.ts +1 -1
  110. package/src/lib/server/agents/agent-service.ts +429 -0
  111. package/src/lib/server/agents/agent-thread-session.ts +6 -5
  112. package/src/lib/server/agents/autonomy-contract.ts +1 -4
  113. package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
  114. package/src/lib/server/agents/delegation-advisory.ts +251 -0
  115. package/src/lib/server/agents/main-agent-loop.ts +98 -40
  116. package/src/lib/server/agents/subagent-runtime.ts +12 -0
  117. package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
  118. package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
  119. package/src/lib/server/build-llm.ts +7 -15
  120. package/src/lib/server/capability-router.test.ts +70 -1
  121. package/src/lib/server/capability-router.ts +24 -99
  122. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
  123. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
  124. package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
  125. package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
  126. package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
  127. package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
  128. package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
  129. package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
  130. package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
  131. package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
  132. package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
  133. package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
  134. package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
  135. package/src/lib/server/chat-execution/message-classifier.ts +74 -32
  136. package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
  137. package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
  138. package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
  139. package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
  140. package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
  141. package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
  142. package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
  143. package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
  144. package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
  145. package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
  146. package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
  147. package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
  148. package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
  149. package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
  150. package/src/lib/server/chats/chat-session-service.ts +410 -0
  151. package/src/lib/server/connectors/access.ts +1 -1
  152. package/src/lib/server/connectors/commands.ts +7 -6
  153. package/src/lib/server/connectors/connector-inbound.ts +14 -7
  154. package/src/lib/server/connectors/connector-outbound.ts +16 -11
  155. package/src/lib/server/connectors/connector-service.ts +453 -0
  156. package/src/lib/server/connectors/delivery.ts +17 -12
  157. package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
  158. package/src/lib/server/connectors/media.ts +1 -1
  159. package/src/lib/server/connectors/response-media.ts +1 -1
  160. package/src/lib/server/connectors/session-consolidation.ts +11 -7
  161. package/src/lib/server/connectors/session.ts +9 -7
  162. package/src/lib/server/connectors/voice-note.ts +2 -1
  163. package/src/lib/server/context-manager.ts +20 -1
  164. package/src/lib/server/cost.ts +2 -3
  165. package/src/lib/server/credentials/credential-repository.ts +43 -4
  166. package/src/lib/server/credentials/credential-service.ts +112 -0
  167. package/src/lib/server/daemon/admin-metadata.ts +64 -0
  168. package/src/lib/server/daemon/controller.ts +577 -0
  169. package/src/lib/server/daemon/daemon-runtime.ts +352 -0
  170. package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
  171. package/src/lib/server/daemon/types.ts +101 -0
  172. package/src/lib/server/embeddings.ts +3 -9
  173. package/src/lib/server/eval/agent-regression.ts +3 -2
  174. package/src/lib/server/eval/runner.ts +2 -2
  175. package/src/lib/server/execution-brief.test.ts +167 -0
  176. package/src/lib/server/execution-brief.ts +295 -0
  177. package/src/lib/server/execution-engine/chat-turn.ts +9 -0
  178. package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
  179. package/src/lib/server/execution-engine/index.ts +35 -0
  180. package/src/lib/server/execution-engine/task-attempt.ts +303 -0
  181. package/src/lib/server/execution-engine/types.ts +33 -0
  182. package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
  183. package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
  184. package/src/lib/server/memory/session-archive-memory.ts +12 -10
  185. package/src/lib/server/messages/message-repository.ts +330 -0
  186. package/src/lib/server/missions/mission-service/core.ts +8 -6
  187. package/src/lib/server/openclaw/agent-resolver.ts +2 -3
  188. package/src/lib/server/openclaw/doctor.ts +1 -1
  189. package/src/lib/server/openclaw/gateway.test.ts +10 -1
  190. package/src/lib/server/openclaw/gateway.ts +5 -14
  191. package/src/lib/server/openclaw/health.ts +3 -11
  192. package/src/lib/server/openclaw/sync.ts +8 -6
  193. package/src/lib/server/persistence/storage-context.ts +3 -0
  194. package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
  195. package/src/lib/server/protocols/protocol-normalization.ts +1 -1
  196. package/src/lib/server/protocols/protocol-queries.ts +13 -7
  197. package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
  198. package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
  199. package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
  200. package/src/lib/server/protocols/protocol-swarm.ts +8 -8
  201. package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
  202. package/src/lib/server/protocols/protocol-templates.ts +4 -2
  203. package/src/lib/server/protocols/protocol-types.ts +10 -7
  204. package/src/lib/server/provider-endpoint.ts +7 -12
  205. package/src/lib/server/provider-model-discovery.ts +2 -11
  206. package/src/lib/server/query-expansion.ts +5 -6
  207. package/src/lib/server/run-context.test.ts +365 -0
  208. package/src/lib/server/run-context.ts +367 -0
  209. package/src/lib/server/runtime/heartbeat-service.ts +7 -5
  210. package/src/lib/server/runtime/queue/core.ts +61 -190
  211. package/src/lib/server/runtime/run-ledger.ts +8 -0
  212. package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
  213. package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
  214. package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
  215. package/src/lib/server/schedules/schedule-route-service.ts +230 -0
  216. package/src/lib/server/service-result.ts +16 -0
  217. package/src/lib/server/session-note.ts +2 -3
  218. package/src/lib/server/session-reset-policy.ts +4 -3
  219. package/src/lib/server/session-tools/connector.ts +9 -6
  220. package/src/lib/server/session-tools/context-mgmt.ts +58 -9
  221. package/src/lib/server/session-tools/crud.ts +162 -10
  222. package/src/lib/server/session-tools/delegate.ts +1 -1
  223. package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
  224. package/src/lib/server/session-tools/memory.ts +6 -4
  225. package/src/lib/server/session-tools/session-info.test.ts +56 -0
  226. package/src/lib/server/session-tools/session-info.ts +119 -12
  227. package/src/lib/server/session-tools/skill-runtime.ts +3 -1
  228. package/src/lib/server/session-tools/skills.ts +15 -15
  229. package/src/lib/server/session-tools/subagent.test.ts +115 -1
  230. package/src/lib/server/session-tools/subagent.ts +125 -7
  231. package/src/lib/server/session-tools/team-context.ts +4 -3
  232. package/src/lib/server/session-tools/wallet.ts +0 -58
  233. package/src/lib/server/sessions/session-lineage.ts +55 -0
  234. package/src/lib/server/sessions/session-repository.ts +2 -2
  235. package/src/lib/server/skills/learned-skills.ts +24 -23
  236. package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
  237. package/src/lib/server/skills/skill-repository.ts +136 -13
  238. package/src/lib/server/skills/skill-suggestions.ts +25 -28
  239. package/src/lib/server/storage-normalization.test.ts +44 -267
  240. package/src/lib/server/storage-normalization.ts +75 -0
  241. package/src/lib/server/storage.ts +19 -0
  242. package/src/lib/server/structured-extract.ts +3 -14
  243. package/src/lib/server/tasks/task-followups.ts +16 -11
  244. package/src/lib/server/tasks/task-result.test.ts +25 -29
  245. package/src/lib/server/tasks/task-result.ts +5 -9
  246. package/src/lib/server/tasks/task-route-service.ts +449 -0
  247. package/src/lib/server/text-normalization.ts +41 -0
  248. package/src/lib/server/tool-planning.ts +6 -42
  249. package/src/lib/server/upload-path.ts +5 -0
  250. package/src/lib/server/working-state/extraction.ts +614 -0
  251. package/src/lib/server/working-state/normalization.ts +866 -0
  252. package/src/lib/server/working-state/prompt.ts +60 -0
  253. package/src/lib/server/working-state/repository.ts +38 -0
  254. package/src/lib/server/working-state/service.test.ts +253 -0
  255. package/src/lib/server/working-state/service.ts +293 -0
  256. package/src/lib/validation/schemas.ts +1 -0
  257. package/src/lib/ws-client.ts +3 -3
  258. package/src/stores/slices/task-slice.ts +1 -4
  259. package/src/stores/use-chatroom-store.ts +2 -2
  260. package/src/types/index.ts +277 -12
@@ -0,0 +1,274 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
2
+ import { api } from '@/lib/app/api-client'
3
+ import { credentialQueryKeys } from '@/features/credentials/queries'
4
+ import type {
5
+ GatewayProfile,
6
+ OpenClawDevicePairRequest,
7
+ OpenClawNode,
8
+ OpenClawNodePairRequest,
9
+ OpenClawPairedDevice,
10
+ } from '@/types'
11
+
12
+ type QueryOptions = {
13
+ enabled?: boolean
14
+ }
15
+
16
+ export interface GatewayDiscoveryResult {
17
+ host: string
18
+ port: number
19
+ healthy: boolean
20
+ models?: string[]
21
+ error?: string
22
+ }
23
+
24
+ export interface GatewayRpcResponse<T> {
25
+ ok?: boolean
26
+ result?: T
27
+ error?: string
28
+ }
29
+
30
+ interface NodeListResult {
31
+ nodes?: OpenClawNode[]
32
+ }
33
+
34
+ interface PairingListResult<T> {
35
+ pending?: T[]
36
+ paired?: OpenClawPairedDevice[]
37
+ }
38
+
39
+ interface SaveGatewayProfileInput {
40
+ id?: string | null
41
+ payload: Record<string, unknown>
42
+ }
43
+
44
+ interface VerifyOpenClawDeployInput {
45
+ endpoint: string
46
+ token?: string
47
+ }
48
+
49
+ export interface VerifyOpenClawDeployResult {
50
+ ok: boolean
51
+ verify?: {
52
+ ok: boolean
53
+ message?: string
54
+ error?: string
55
+ hint?: string
56
+ models?: string[]
57
+ }
58
+ }
59
+
60
+ export interface RefreshGatewayTopologyResult {
61
+ nodes: OpenClawNode[]
62
+ nodePairings: OpenClawNodePairRequest[]
63
+ devicePairings: OpenClawDevicePairRequest[]
64
+ pairedDevices: OpenClawPairedDevice[]
65
+ }
66
+
67
+ async function invalidateGatewayQueries(queryClient: ReturnType<typeof useQueryClient>) {
68
+ await queryClient.invalidateQueries({ queryKey: gatewayQueryKeys.all })
69
+ }
70
+
71
+ export const gatewayQueryKeys = {
72
+ all: ['gateways'] as const,
73
+ profiles: () => ['gateways', 'profiles'] as const,
74
+ }
75
+
76
+ export function useGatewayProfilesQuery(options: QueryOptions = {}) {
77
+ return useQuery<GatewayProfile[]>({
78
+ queryKey: gatewayQueryKeys.profiles(),
79
+ queryFn: () => api<GatewayProfile[]>('GET', '/gateways'),
80
+ enabled: options.enabled,
81
+ staleTime: 20_000,
82
+ })
83
+ }
84
+
85
+ export function useSaveGatewayProfileMutation() {
86
+ const queryClient = useQueryClient()
87
+ return useMutation({
88
+ mutationFn: ({ id, payload }: SaveGatewayProfileInput) =>
89
+ id ? api('PUT', `/gateways/${id}`, payload) : api('POST', '/gateways', payload),
90
+ onSuccess: async () => {
91
+ await Promise.all([
92
+ invalidateGatewayQueries(queryClient),
93
+ queryClient.invalidateQueries({ queryKey: credentialQueryKeys.all }),
94
+ ])
95
+ },
96
+ })
97
+ }
98
+
99
+ export function useDeleteGatewayProfileMutation() {
100
+ const queryClient = useQueryClient()
101
+ return useMutation({
102
+ mutationFn: (id: string) => api('DELETE', `/gateways/${id}`),
103
+ onSuccess: async () => {
104
+ await invalidateGatewayQueries(queryClient)
105
+ },
106
+ })
107
+ }
108
+
109
+ export function useCloneGatewayProfileMutation() {
110
+ const queryClient = useQueryClient()
111
+ return useMutation({
112
+ mutationFn: (payload: Record<string, unknown>) => api('POST', '/gateways', payload),
113
+ onSuccess: async () => {
114
+ await invalidateGatewayQueries(queryClient)
115
+ },
116
+ })
117
+ }
118
+
119
+ export function useGatewayHealthCheckMutation() {
120
+ const queryClient = useQueryClient()
121
+ return useMutation({
122
+ mutationFn: (id: string) => api('GET', `/gateways/${id}/health`),
123
+ onSuccess: async () => {
124
+ await invalidateGatewayQueries(queryClient)
125
+ },
126
+ })
127
+ }
128
+
129
+ export function useVerifyOpenClawDeployMutation() {
130
+ return useMutation<VerifyOpenClawDeployResult, Error, VerifyOpenClawDeployInput>({
131
+ mutationFn: ({ endpoint, token }) =>
132
+ api<VerifyOpenClawDeployResult>('POST', '/openclaw/deploy', {
133
+ action: 'verify',
134
+ endpoint,
135
+ token: token?.trim() || undefined,
136
+ }),
137
+ })
138
+ }
139
+
140
+ export function useCheckOpenClawGatewayMutation() {
141
+ return useMutation({
142
+ mutationFn: async ({
143
+ endpoint,
144
+ credentialId,
145
+ token,
146
+ }: {
147
+ endpoint: string
148
+ credentialId?: string | null
149
+ token?: string | null
150
+ }) => {
151
+ const params = new URLSearchParams()
152
+ params.set('endpoint', endpoint.trim() || 'http://localhost:18789')
153
+ if (credentialId) params.set('credentialId', credentialId)
154
+ if (token?.trim()) params.set('token', token.trim())
155
+ return api<{ ok: boolean; models: string[]; message?: string; error?: string; hint?: string }>(
156
+ 'GET',
157
+ `/providers/openclaw/health?${params.toString()}`,
158
+ )
159
+ },
160
+ })
161
+ }
162
+
163
+ export function useDiscoverOpenClawGatewaysMutation() {
164
+ return useMutation({
165
+ mutationFn: () => api<{ gateways: GatewayDiscoveryResult[] }>('GET', '/openclaw/discover'),
166
+ })
167
+ }
168
+
169
+ export function useRefreshGatewayTopologyMutation() {
170
+ const queryClient = useQueryClient()
171
+ return useMutation<RefreshGatewayTopologyResult, Error, string>({
172
+ mutationFn: async (profileId) => {
173
+ const [nodesRes, nodePairRes, devicePairRes] = await Promise.all([
174
+ api<GatewayRpcResponse<NodeListResult>>('POST', '/openclaw/gateway', {
175
+ method: 'node.list',
176
+ params: { profileId },
177
+ }),
178
+ api<GatewayRpcResponse<PairingListResult<OpenClawNodePairRequest>>>('POST', '/openclaw/gateway', {
179
+ method: 'node.pair.list',
180
+ params: { profileId },
181
+ }),
182
+ api<GatewayRpcResponse<PairingListResult<OpenClawDevicePairRequest>>>('POST', '/openclaw/gateway', {
183
+ method: 'device.pair.list',
184
+ params: { profileId },
185
+ }),
186
+ ])
187
+
188
+ if (nodesRes.error) throw new Error(nodesRes.error)
189
+ if (nodePairRes.error) throw new Error(nodePairRes.error)
190
+ if (devicePairRes.error) throw new Error(devicePairRes.error)
191
+
192
+ const nodes = Array.isArray(nodesRes.result?.nodes) ? nodesRes.result.nodes : []
193
+ const nodePairings = Array.isArray(nodePairRes.result?.pending) ? nodePairRes.result.pending : []
194
+ const devicePairings = Array.isArray(devicePairRes.result?.pending) ? devicePairRes.result.pending : []
195
+ const pairedDevices = Array.isArray(devicePairRes.result?.paired) ? devicePairRes.result.paired : []
196
+ const stats = {
197
+ nodeCount: nodes.length,
198
+ connectedNodeCount: nodes.filter((node) => node.connected).length,
199
+ pendingNodePairings: nodePairings.length,
200
+ pairedDeviceCount: pairedDevices.length,
201
+ pendingDevicePairings: devicePairings.length,
202
+ }
203
+
204
+ void api('PUT', `/gateways/${profileId}`, { stats }).catch(() => {})
205
+
206
+ return {
207
+ nodes,
208
+ nodePairings,
209
+ devicePairings,
210
+ pairedDevices,
211
+ }
212
+ },
213
+ onSuccess: async () => {
214
+ await invalidateGatewayQueries(queryClient)
215
+ },
216
+ })
217
+ }
218
+
219
+ export function useGatewayPairingDecisionMutation() {
220
+ return useMutation({
221
+ mutationFn: ({
222
+ profileId,
223
+ kind,
224
+ requestId,
225
+ decision,
226
+ }: {
227
+ profileId: string
228
+ kind: 'node' | 'device'
229
+ requestId: string
230
+ decision: 'approve' | 'reject'
231
+ }) =>
232
+ api<GatewayRpcResponse<unknown>>('POST', '/openclaw/gateway', {
233
+ method: kind === 'node'
234
+ ? (decision === 'approve' ? 'node.pair.approve' : 'node.pair.reject')
235
+ : (decision === 'approve' ? 'device.pair.approve' : 'device.pair.reject'),
236
+ params: { profileId, requestId },
237
+ }),
238
+ })
239
+ }
240
+
241
+ export function useGatewayRemoveDeviceMutation() {
242
+ return useMutation({
243
+ mutationFn: ({ profileId, deviceId }: { profileId: string; deviceId: string }) =>
244
+ api<GatewayRpcResponse<unknown>>('POST', '/openclaw/gateway', {
245
+ method: 'device.pair.remove',
246
+ params: { profileId, deviceId },
247
+ }),
248
+ })
249
+ }
250
+
251
+ export function useGatewayInvokeNodeMutation() {
252
+ return useMutation({
253
+ mutationFn: ({
254
+ profileId,
255
+ nodeId,
256
+ command,
257
+ params,
258
+ }: {
259
+ profileId: string
260
+ nodeId: string
261
+ command: string
262
+ params: Record<string, unknown>
263
+ }) =>
264
+ api<GatewayRpcResponse<unknown>>('POST', '/openclaw/gateway', {
265
+ method: 'node.invoke',
266
+ params: {
267
+ profileId,
268
+ nodeId,
269
+ command,
270
+ params,
271
+ },
272
+ }),
273
+ })
274
+ }
@@ -0,0 +1,23 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { api } from '@/lib/app/api-client'
3
+ import type { Mission } from '@/types'
4
+
5
+ type MissionListOptions = {
6
+ enabled?: boolean
7
+ limit?: number
8
+ }
9
+
10
+ export const missionQueryKeys = {
11
+ all: ['missions'] as const,
12
+ list: (limit: number) => ['missions', 'list', { limit }] as const,
13
+ }
14
+
15
+ export function useMissionsQuery(options: MissionListOptions = {}) {
16
+ const limit = options.limit ?? 80
17
+ return useQuery<Mission[]>({
18
+ queryKey: missionQueryKeys.list(limit),
19
+ queryFn: () => api<Mission[]>('GET', `/missions?limit=${limit}`),
20
+ enabled: options.enabled,
21
+ staleTime: 30_000,
22
+ })
23
+ }
@@ -0,0 +1,20 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { fetchProjects } from '@/lib/projects'
3
+ import type { Project } from '@/types'
4
+
5
+ type QueryOptions = {
6
+ enabled?: boolean
7
+ }
8
+
9
+ export const projectQueryKeys = {
10
+ all: ['projects'] as const,
11
+ }
12
+
13
+ export function useProjectsQuery(options: QueryOptions = {}) {
14
+ return useQuery<Record<string, Project>>({
15
+ queryKey: projectQueryKeys.all,
16
+ queryFn: fetchProjects,
17
+ enabled: options.enabled,
18
+ staleTime: 60_000,
19
+ })
20
+ }
@@ -0,0 +1,149 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
2
+ import { api } from '@/lib/app/api-client'
3
+ import type { ProtocolRunDetail } from '@/lib/server/protocols/protocol-types'
4
+ import type { ProtocolRun, ProtocolStepDefinition, ProtocolTemplate } from '@/types'
5
+
6
+ export type ProtocolRunListParams = {
7
+ limit?: number
8
+ missionId?: string | null
9
+ taskId?: string | null
10
+ sessionId?: string | null
11
+ parentChatroomId?: string | null
12
+ }
13
+
14
+ export interface ProtocolRunCreatePayload {
15
+ title: string
16
+ templateId?: string | null
17
+ participantAgentIds: string[]
18
+ facilitatorAgentId?: string | null
19
+ sessionId?: string | null
20
+ parentChatroomId?: string | null
21
+ missionId?: string | null
22
+ taskId?: string | null
23
+ autoStart?: boolean
24
+ createTranscript?: boolean
25
+ config?: Record<string, unknown> | null
26
+ }
27
+
28
+ export interface ProtocolTemplatePayload {
29
+ name: string
30
+ description: string
31
+ tags: string[]
32
+ recommendedOutputs: string[]
33
+ singleAgentAllowed: boolean
34
+ steps: ProtocolStepDefinition[]
35
+ entryStepId?: string | null
36
+ }
37
+
38
+ export type ProtocolRunActionPayload =
39
+ | { action: 'start' | 'pause' | 'resume' | 'retry_phase' | 'skip_phase' | 'cancel' | 'archive' }
40
+ | { action: 'inject_context'; context: string }
41
+
42
+ type QueryOptions = {
43
+ enabled?: boolean
44
+ }
45
+
46
+ type ProtocolRunListQueryOptions = ProtocolRunListParams & QueryOptions
47
+
48
+ function normalizeRunListParams(params: ProtocolRunListParams = {}) {
49
+ return {
50
+ limit: params.limit ?? 120,
51
+ missionId: params.missionId ?? null,
52
+ taskId: params.taskId ?? null,
53
+ sessionId: params.sessionId ?? null,
54
+ parentChatroomId: params.parentChatroomId ?? null,
55
+ }
56
+ }
57
+
58
+ function buildRunListQueryString(params: ReturnType<typeof normalizeRunListParams>): string {
59
+ const query = new URLSearchParams()
60
+ query.set('limit', String(params.limit))
61
+ if (params.missionId) query.set('missionId', params.missionId)
62
+ if (params.taskId) query.set('taskId', params.taskId)
63
+ if (params.sessionId) query.set('sessionId', params.sessionId)
64
+ if (params.parentChatroomId) query.set('parentChatroomId', params.parentChatroomId)
65
+ return query.toString()
66
+ }
67
+
68
+ export const protocolQueryKeys = {
69
+ all: ['protocols'] as const,
70
+ templates: () => ['protocols', 'templates'] as const,
71
+ runs: () => ['protocols', 'runs'] as const,
72
+ runList: (params: ReturnType<typeof normalizeRunListParams>) => ['protocols', 'runs', params] as const,
73
+ runDetail: (runId: string | null) => ['protocols', 'run', runId] as const,
74
+ }
75
+
76
+ export function useProtocolTemplatesQuery(options: QueryOptions = {}) {
77
+ return useQuery<ProtocolTemplate[]>({
78
+ queryKey: protocolQueryKeys.templates(),
79
+ queryFn: () => api<ProtocolTemplate[]>('GET', '/protocols/templates'),
80
+ enabled: options.enabled,
81
+ staleTime: 30_000,
82
+ })
83
+ }
84
+
85
+ export function useProtocolRunsQuery(options: ProtocolRunListQueryOptions = {}) {
86
+ const params = normalizeRunListParams(options)
87
+ return useQuery<ProtocolRun[]>({
88
+ queryKey: protocolQueryKeys.runList(params),
89
+ queryFn: () => api<ProtocolRun[]>('GET', `/protocols/runs?${buildRunListQueryString(params)}`),
90
+ enabled: options.enabled,
91
+ staleTime: 5_000,
92
+ })
93
+ }
94
+
95
+ export function useProtocolRunDetailQuery(runId: string | null, options: QueryOptions = {}) {
96
+ return useQuery<ProtocolRunDetail | null>({
97
+ queryKey: protocolQueryKeys.runDetail(runId),
98
+ queryFn: () => api<ProtocolRunDetail>('GET', `/protocols/runs/${runId}`),
99
+ enabled: options.enabled ?? Boolean(runId),
100
+ staleTime: 5_000,
101
+ })
102
+ }
103
+
104
+ export function useCreateProtocolRunMutation() {
105
+ const queryClient = useQueryClient()
106
+ return useMutation({
107
+ mutationFn: (payload: ProtocolRunCreatePayload) => api<ProtocolRun>('POST', '/protocols/runs', payload),
108
+ onSuccess: async () => {
109
+ await queryClient.invalidateQueries({ queryKey: protocolQueryKeys.all })
110
+ },
111
+ })
112
+ }
113
+
114
+ export function useProtocolRunActionMutation() {
115
+ const queryClient = useQueryClient()
116
+ return useMutation({
117
+ mutationFn: ({ runId, payload }: { runId: string; payload: ProtocolRunActionPayload }) =>
118
+ api('POST', `/protocols/runs/${runId}/actions`, payload),
119
+ onSettled: async (_data, _error, variables) => {
120
+ await Promise.all([
121
+ queryClient.invalidateQueries({ queryKey: protocolQueryKeys.runs() }),
122
+ queryClient.invalidateQueries({ queryKey: protocolQueryKeys.runDetail(variables.runId) }),
123
+ ])
124
+ },
125
+ })
126
+ }
127
+
128
+ export function useUpsertProtocolTemplateMutation() {
129
+ const queryClient = useQueryClient()
130
+ return useMutation<ProtocolTemplate, Error, { templateId?: string | null; payload: ProtocolTemplatePayload }>({
131
+ mutationFn: ({ templateId, payload }: { templateId?: string | null; payload: ProtocolTemplatePayload }) =>
132
+ templateId
133
+ ? api<ProtocolTemplate>('PATCH', `/protocols/templates/${templateId}`, payload)
134
+ : api<ProtocolTemplate>('POST', '/protocols/templates', payload),
135
+ onSuccess: async () => {
136
+ await queryClient.invalidateQueries({ queryKey: protocolQueryKeys.all })
137
+ },
138
+ })
139
+ }
140
+
141
+ export function useDeleteProtocolTemplateMutation() {
142
+ const queryClient = useQueryClient()
143
+ return useMutation({
144
+ mutationFn: (templateId: string) => api('DELETE', `/protocols/templates/${templateId}`),
145
+ onSuccess: async () => {
146
+ await queryClient.invalidateQueries({ queryKey: protocolQueryKeys.all })
147
+ },
148
+ })
149
+ }
@@ -0,0 +1,142 @@
1
+ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
2
+ import { api } from '@/lib/app/api-client'
3
+ import {
4
+ createProviderConfig,
5
+ deleteProviderConfig,
6
+ fetchProviderConfigs,
7
+ updateProviderConfig,
8
+ } from '@/lib/provider-config'
9
+ import {
10
+ fetchProviderModelDiscovery,
11
+ type DiscoverProviderModelsParams,
12
+ } from '@/lib/provider-model-discovery-client'
13
+ import { fetchProviders } from '@/lib/chat/chats'
14
+ import type {
15
+ ProviderConfig,
16
+ ProviderInfo,
17
+ ProviderModelDiscoveryResult,
18
+ } from '@/types'
19
+
20
+ type QueryOptions = {
21
+ enabled?: boolean
22
+ }
23
+
24
+ interface SaveBuiltinProviderInput {
25
+ id: string
26
+ models: string[]
27
+ isEnabled: boolean
28
+ }
29
+
30
+ interface SaveCustomProviderInput {
31
+ id?: string | null
32
+ data: Partial<ProviderConfig>
33
+ }
34
+
35
+ interface CheckProviderConnectionInput {
36
+ provider: string
37
+ credentialId?: string | null
38
+ endpoint?: string | null
39
+ }
40
+
41
+ async function invalidateProviderQueries(queryClient: ReturnType<typeof useQueryClient>) {
42
+ await queryClient.invalidateQueries({ queryKey: providerQueryKeys.all })
43
+ }
44
+
45
+ export const providerQueryKeys = {
46
+ all: ['provider-resources'] as const,
47
+ catalog: () => ['provider-resources', 'catalog'] as const,
48
+ configs: () => ['provider-resources', 'configs'] as const,
49
+ }
50
+
51
+ export function useProvidersQuery(options: QueryOptions = {}) {
52
+ return useQuery<ProviderInfo[]>({
53
+ queryKey: providerQueryKeys.catalog(),
54
+ queryFn: fetchProviders,
55
+ enabled: options.enabled,
56
+ staleTime: 30_000,
57
+ })
58
+ }
59
+
60
+ export function useProviderConfigsQuery(options: QueryOptions = {}) {
61
+ return useQuery<ProviderConfig[]>({
62
+ queryKey: providerQueryKeys.configs(),
63
+ queryFn: fetchProviderConfigs,
64
+ enabled: options.enabled,
65
+ staleTime: 30_000,
66
+ })
67
+ }
68
+
69
+ export function useToggleProviderMutation() {
70
+ const queryClient = useQueryClient()
71
+ return useMutation({
72
+ mutationFn: ({ id, isEnabled }: { id: string; isEnabled: boolean }) =>
73
+ api('PUT', `/providers/${id}`, { isEnabled }),
74
+ onSuccess: async () => {
75
+ await invalidateProviderQueries(queryClient)
76
+ },
77
+ })
78
+ }
79
+
80
+ export function useSaveBuiltinProviderMutation() {
81
+ const queryClient = useQueryClient()
82
+ return useMutation({
83
+ mutationFn: async ({ id, models, isEnabled }: SaveBuiltinProviderInput) => {
84
+ await api('PUT', `/providers/${id}/models`, { models })
85
+ return api('PUT', `/providers/${id}`, {
86
+ type: 'builtin',
87
+ isEnabled,
88
+ })
89
+ },
90
+ onSuccess: async () => {
91
+ await invalidateProviderQueries(queryClient)
92
+ },
93
+ })
94
+ }
95
+
96
+ export function useSaveCustomProviderMutation() {
97
+ const queryClient = useQueryClient()
98
+ return useMutation({
99
+ mutationFn: ({ id, data }: SaveCustomProviderInput) =>
100
+ id ? updateProviderConfig(id, data) : createProviderConfig(data),
101
+ onSuccess: async () => {
102
+ await invalidateProviderQueries(queryClient)
103
+ },
104
+ })
105
+ }
106
+
107
+ export function useDeleteProviderMutation() {
108
+ const queryClient = useQueryClient()
109
+ return useMutation({
110
+ mutationFn: (id: string) => deleteProviderConfig(id),
111
+ onSuccess: async () => {
112
+ await invalidateProviderQueries(queryClient)
113
+ },
114
+ })
115
+ }
116
+
117
+ export function useResetProviderModelsMutation() {
118
+ const queryClient = useQueryClient()
119
+ return useMutation({
120
+ mutationFn: (id: string) => api('DELETE', `/providers/${id}/models`),
121
+ onSuccess: async () => {
122
+ await invalidateProviderQueries(queryClient)
123
+ },
124
+ })
125
+ }
126
+
127
+ export function useCheckProviderConnectionMutation() {
128
+ return useMutation({
129
+ mutationFn: ({ provider, credentialId, endpoint }: CheckProviderConnectionInput) =>
130
+ api<{ ok: boolean; message: string }>('POST', '/setup/check-provider', {
131
+ provider,
132
+ credentialId,
133
+ endpoint,
134
+ }),
135
+ })
136
+ }
137
+
138
+ export function useProviderModelDiscoveryMutation() {
139
+ return useMutation<ProviderModelDiscoveryResult, Error, DiscoverProviderModelsParams>({
140
+ mutationFn: fetchProviderModelDiscovery,
141
+ })
142
+ }
@@ -0,0 +1,20 @@
1
+ import { useQuery } from '@tanstack/react-query'
2
+ import { api } from '@/lib/app/api-client'
3
+ import type { AppSettings } from '@/types'
4
+
5
+ type QueryOptions = {
6
+ enabled?: boolean
7
+ }
8
+
9
+ export const settingsQueryKeys = {
10
+ app: ['settings', 'app'] as const,
11
+ }
12
+
13
+ export function useAppSettingsQuery(options: QueryOptions = {}) {
14
+ return useQuery<AppSettings>({
15
+ queryKey: settingsQueryKeys.app,
16
+ queryFn: () => api<AppSettings>('GET', '/settings'),
17
+ enabled: options.enabled,
18
+ staleTime: 60_000,
19
+ })
20
+ }