@swarmclawai/swarmclaw 0.7.3 → 0.7.4

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 (147) hide show
  1. package/README.md +47 -40
  2. package/bin/package-manager.js +157 -0
  3. package/bin/package-manager.test.js +90 -0
  4. package/bin/server-cmd.js +38 -7
  5. package/bin/swarmclaw.js +54 -4
  6. package/bin/update-cmd.js +48 -10
  7. package/bin/update-cmd.test.js +55 -0
  8. package/package.json +8 -3
  9. package/scripts/postinstall.mjs +26 -0
  10. package/src/app/api/agents/[id]/route.ts +17 -0
  11. package/src/app/api/agents/[id]/thread/route.ts +3 -1
  12. package/src/app/api/agents/route.ts +23 -1
  13. package/src/app/api/auth/route.ts +1 -1
  14. package/src/app/api/chatrooms/[id]/chat/route.ts +16 -5
  15. package/src/app/api/chatrooms/[id]/pins/route.ts +2 -1
  16. package/src/app/api/chatrooms/[id]/reactions/route.ts +2 -1
  17. package/src/app/api/chatrooms/[id]/route.ts +6 -0
  18. package/src/app/api/chats/[id]/route.ts +12 -0
  19. package/src/app/api/chats/heartbeat/route.ts +2 -1
  20. package/src/app/api/chats/route.ts +7 -1
  21. package/src/app/api/external-agents/[id]/heartbeat/route.ts +33 -0
  22. package/src/app/api/external-agents/[id]/route.ts +31 -0
  23. package/src/app/api/external-agents/register/route.ts +3 -0
  24. package/src/app/api/external-agents/route.ts +66 -0
  25. package/src/app/api/gateways/[id]/health/route.ts +28 -0
  26. package/src/app/api/gateways/[id]/route.ts +79 -0
  27. package/src/app/api/gateways/route.ts +57 -0
  28. package/src/app/api/openclaw/gateway/route.ts +10 -7
  29. package/src/app/api/openclaw/skills/route.ts +1 -1
  30. package/src/app/api/providers/[id]/discover-models/route.ts +27 -0
  31. package/src/app/api/schedules/[id]/route.ts +38 -9
  32. package/src/app/api/schedules/route.ts +51 -28
  33. package/src/app/api/settings/route.ts +6 -10
  34. package/src/app/api/setup/doctor/route.ts +6 -4
  35. package/src/app/api/tasks/[id]/route.ts +2 -1
  36. package/src/app/api/tasks/bulk/route.ts +2 -2
  37. package/src/app/page.tsx +126 -15
  38. package/src/cli/binary.test.js +142 -0
  39. package/src/cli/index.js +34 -11
  40. package/src/cli/index.test.js +195 -0
  41. package/src/cli/index.ts +20 -4
  42. package/src/cli/server-cmd.test.js +59 -0
  43. package/src/cli/spec.js +20 -2
  44. package/src/components/agents/agent-sheet.tsx +249 -7
  45. package/src/components/agents/inspector-panel.tsx +3 -2
  46. package/src/components/agents/sandbox-env-panel.tsx +4 -1
  47. package/src/components/auth/setup-wizard.tsx +970 -275
  48. package/src/components/chat/chat-area.tsx +41 -14
  49. package/src/components/chat/chat-card.tsx +2 -1
  50. package/src/components/chat/chat-header.tsx +8 -13
  51. package/src/components/chat/chat-list.tsx +58 -20
  52. package/src/components/chat/message-list.tsx +142 -18
  53. package/src/components/chatrooms/chatroom-input.tsx +96 -33
  54. package/src/components/chatrooms/chatroom-list.tsx +141 -72
  55. package/src/components/chatrooms/chatroom-message.tsx +7 -6
  56. package/src/components/chatrooms/chatroom-sheet.tsx +13 -1
  57. package/src/components/chatrooms/chatroom-tool-request-banner.tsx +5 -2
  58. package/src/components/chatrooms/chatroom-view.tsx +157 -86
  59. package/src/components/chatrooms/reaction-picker.tsx +38 -33
  60. package/src/components/gateways/gateway-sheet.tsx +567 -0
  61. package/src/components/input/chat-input.tsx +135 -86
  62. package/src/components/layout/app-layout.tsx +2 -0
  63. package/src/components/memory/memory-browser.tsx +71 -6
  64. package/src/components/memory/memory-card.tsx +18 -0
  65. package/src/components/memory/memory-detail.tsx +58 -31
  66. package/src/components/memory/memory-sheet.tsx +32 -4
  67. package/src/components/projects/project-detail.tsx +7 -2
  68. package/src/components/providers/provider-list.tsx +158 -2
  69. package/src/components/providers/provider-sheet.tsx +81 -70
  70. package/src/components/shared/bottom-sheet.tsx +31 -15
  71. package/src/components/shared/confirm-dialog.tsx +45 -30
  72. package/src/components/shared/model-combobox.tsx +90 -8
  73. package/src/components/shared/settings/section-heartbeat.tsx +11 -6
  74. package/src/components/shared/settings/section-orchestrator.tsx +3 -0
  75. package/src/components/shared/settings/settings-page.tsx +5 -3
  76. package/src/components/tasks/approvals-panel.tsx +7 -1
  77. package/src/components/ui/dialog.tsx +2 -2
  78. package/src/components/wallets/wallet-approval-dialog.tsx +59 -54
  79. package/src/lib/heartbeat-defaults.ts +48 -0
  80. package/src/lib/memory-presentation.ts +59 -0
  81. package/src/lib/provider-model-discovery-client.ts +29 -0
  82. package/src/lib/providers/index.ts +12 -5
  83. package/src/lib/runtime-loop.ts +105 -3
  84. package/src/lib/safe-storage.ts +6 -1
  85. package/src/lib/server/agent-runtime-config.test.ts +141 -0
  86. package/src/lib/server/agent-runtime-config.ts +277 -0
  87. package/src/lib/server/approvals-auto-approve.test.ts +59 -0
  88. package/src/lib/server/build-llm.test.ts +13 -5
  89. package/src/lib/server/chat-execution-tool-events.test.ts +87 -2
  90. package/src/lib/server/chat-execution.ts +159 -71
  91. package/src/lib/server/chatroom-helpers.test.ts +7 -0
  92. package/src/lib/server/chatroom-helpers.ts +99 -6
  93. package/src/lib/server/chatroom-session-persistence.test.ts +87 -0
  94. package/src/lib/server/connectors/manager.ts +89 -61
  95. package/src/lib/server/connectors/slack.ts +1 -1
  96. package/src/lib/server/daemon-state.ts +3 -2
  97. package/src/lib/server/eval/agent-regression.test.ts +47 -0
  98. package/src/lib/server/eval/agent-regression.ts +1742 -0
  99. package/src/lib/server/eval/runner.ts +11 -1
  100. package/src/lib/server/eval/store.ts +2 -1
  101. package/src/lib/server/heartbeat-service.ts +10 -4
  102. package/src/lib/server/main-agent-loop.ts +13 -6
  103. package/src/lib/server/openclaw-exec-config.ts +4 -2
  104. package/src/lib/server/openclaw-gateway.ts +123 -36
  105. package/src/lib/server/orchestrator-lg.ts +1 -2
  106. package/src/lib/server/orchestrator.ts +3 -2
  107. package/src/lib/server/plugins.test.ts +9 -1
  108. package/src/lib/server/plugins.ts +12 -2
  109. package/src/lib/server/provider-model-discovery.ts +481 -0
  110. package/src/lib/server/queue.ts +1 -1
  111. package/src/lib/server/runtime-settings.test.ts +119 -0
  112. package/src/lib/server/runtime-settings.ts +12 -92
  113. package/src/lib/server/schedule-normalization.ts +187 -0
  114. package/src/lib/server/session-tools/autonomy-tools.test.ts +23 -0
  115. package/src/lib/server/session-tools/crud.ts +27 -3
  116. package/src/lib/server/session-tools/discovery-approvals.test.ts +170 -0
  117. package/src/lib/server/session-tools/discovery.ts +18 -8
  118. package/src/lib/server/session-tools/file-normalize.test.ts +5 -0
  119. package/src/lib/server/session-tools/file.ts +8 -2
  120. package/src/lib/server/session-tools/http.ts +9 -3
  121. package/src/lib/server/session-tools/index.ts +31 -1
  122. package/src/lib/server/session-tools/manage-schedules.test.ts +137 -0
  123. package/src/lib/server/session-tools/monitor.ts +14 -7
  124. package/src/lib/server/session-tools/openclaw-nodes.test.ts +111 -0
  125. package/src/lib/server/session-tools/openclaw-nodes.ts +86 -20
  126. package/src/lib/server/session-tools/platform.ts +1 -1
  127. package/src/lib/server/session-tools/plugin-creator.ts +9 -2
  128. package/src/lib/server/session-tools/sandbox.ts +51 -92
  129. package/src/lib/server/session-tools/session-info.ts +22 -1
  130. package/src/lib/server/session-tools/session-tools-wiring.test.ts +23 -0
  131. package/src/lib/server/session-tools/shell.ts +2 -2
  132. package/src/lib/server/session-tools/subagent.ts +3 -1
  133. package/src/lib/server/session-tools/web.ts +73 -30
  134. package/src/lib/server/storage.ts +29 -3
  135. package/src/lib/server/stream-agent-chat.test.ts +61 -0
  136. package/src/lib/server/stream-agent-chat.ts +139 -4
  137. package/src/lib/server/structured-extract.ts +1 -1
  138. package/src/lib/server/task-mention.ts +0 -1
  139. package/src/lib/server/tool-aliases.ts +37 -6
  140. package/src/lib/server/tool-capability-policy.ts +1 -1
  141. package/src/lib/setup-defaults.ts +352 -11
  142. package/src/lib/tool-definitions.ts +3 -4
  143. package/src/lib/validation/schemas.ts +55 -1
  144. package/src/stores/use-app-store.ts +43 -1
  145. package/src/stores/use-chatroom-store.ts +153 -26
  146. package/src/types/index.ts +189 -6
  147. package/src/app/api/chats/[id]/main-loop/route.ts +0 -13
@@ -11,13 +11,25 @@ interface ToolEvent {
11
11
  output?: string
12
12
  }
13
13
 
14
- interface StreamingAgent {
14
+ export interface StreamingAgent {
15
15
  text: string
16
16
  name: string
17
17
  error?: string
18
18
  toolEvents: ToolEvent[]
19
19
  }
20
20
 
21
+ interface QueuedChatroomMessage {
22
+ id: string
23
+ chatroomId: string
24
+ text: string
25
+ pendingFiles: PendingFile[]
26
+ replyingTo: ChatroomMessage | null
27
+ }
28
+
29
+ function nextQueuedId() {
30
+ return `queued-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
31
+ }
32
+
21
33
  interface ChatroomState {
22
34
  chatrooms: Record<string, Chatroom>
23
35
  currentChatroomId: string | null
@@ -36,6 +48,10 @@ interface ChatroomState {
36
48
  replyingTo: ChatroomMessage | null
37
49
  setReplyingTo: (msg: ChatroomMessage | null) => void
38
50
 
51
+ queuedMessages: QueuedChatroomMessage[]
52
+ removeQueuedMessage: (id: string) => void
53
+ shiftQueuedMessage: () => QueuedChatroomMessage | undefined
54
+
39
55
  loadChatrooms: () => Promise<void>
40
56
  createChatroom: (data: { name: string; description?: string; agentIds?: string[]; chatMode?: 'sequential' | 'parallel'; autoAddress?: boolean; routingRules?: ChatroomRoutingRule[] }) => Promise<Chatroom>
41
57
  updateChatroom: (id: string, data: Partial<Chatroom>) => Promise<void>
@@ -73,6 +89,15 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
73
89
  // Reply-to
74
90
  replyingTo: null,
75
91
  setReplyingTo: (msg) => set({ replyingTo: msg }),
92
+ queuedMessages: [],
93
+ removeQueuedMessage: (id) => set((s) => ({ queuedMessages: s.queuedMessages.filter((item) => item.id !== id) })),
94
+ shiftQueuedMessage: () => {
95
+ const queue = get().queuedMessages
96
+ if (!queue.length) return undefined
97
+ const next = queue[0]
98
+ set({ queuedMessages: queue.slice(1) })
99
+ return next
100
+ },
76
101
 
77
102
  loadChatrooms: async () => {
78
103
  const chatrooms = await api<Record<string, Chatroom>>('GET', '/chatrooms')
@@ -106,9 +131,26 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
106
131
 
107
132
  sendMessage: async (text) => {
108
133
  const { currentChatroomId, streaming, pendingFiles, replyingTo } = get()
109
- if (!currentChatroomId || streaming || (!text.trim() && !pendingFiles.length)) return
110
-
111
- set({ streaming: true, streamingAgents: new Map(), pendingFiles: [], replyingTo: null })
134
+ if (!currentChatroomId || (!text.trim() && !pendingFiles.length)) return
135
+ const targetChatroomId = currentChatroomId
136
+
137
+ if (streaming) {
138
+ set((s) => ({
139
+ queuedMessages: [
140
+ ...s.queuedMessages,
141
+ {
142
+ id: nextQueuedId(),
143
+ chatroomId: targetChatroomId,
144
+ text,
145
+ pendingFiles: [...pendingFiles],
146
+ replyingTo,
147
+ },
148
+ ],
149
+ pendingFiles: [],
150
+ replyingTo: null,
151
+ }))
152
+ return
153
+ }
112
154
 
113
155
  const imagePath = pendingFiles.length > 0 && pendingFiles[0].file.type.startsWith('image/')
114
156
  ? pendingFiles[0].path
@@ -116,10 +158,12 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
116
158
  const attachedFiles = pendingFiles.length > 0
117
159
  ? pendingFiles.map((f) => f.path)
118
160
  : undefined
161
+ const optimisticText = text.trim() || 'See attached file(s).'
162
+ let started = false
119
163
 
120
164
  const key = getStoredAccessKey()
121
165
  try {
122
- const res = await fetch(`/api/chatrooms/${currentChatroomId}/chat`, {
166
+ const res = await fetch(`/api/chatrooms/${targetChatroomId}/chat`, {
123
167
  method: 'POST',
124
168
  headers: {
125
169
  'Content-Type': 'application/json',
@@ -134,10 +178,43 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
134
178
  })
135
179
 
136
180
  if (!res.ok || !res.body) {
137
- set({ streaming: false })
138
181
  return
139
182
  }
140
183
 
184
+ started = true
185
+ set((s) => {
186
+ const existingChatroom = s.chatrooms[targetChatroomId]
187
+ const optimisticMessage: ChatroomMessage = {
188
+ id: `local-${Date.now()}`,
189
+ senderId: 'user',
190
+ senderName: 'You',
191
+ role: 'user',
192
+ text: optimisticText,
193
+ mentions: [],
194
+ reactions: [],
195
+ time: Date.now(),
196
+ ...(imagePath ? { imagePath } : {}),
197
+ ...(attachedFiles ? { attachedFiles } : {}),
198
+ ...(replyingTo ? { replyToId: replyingTo.id } : {}),
199
+ }
200
+ return {
201
+ streaming: true,
202
+ streamingAgents: new Map(),
203
+ pendingFiles: [],
204
+ replyingTo: null,
205
+ chatrooms: existingChatroom
206
+ ? {
207
+ ...s.chatrooms,
208
+ [targetChatroomId]: {
209
+ ...existingChatroom,
210
+ messages: [...existingChatroom.messages, optimisticMessage],
211
+ updatedAt: optimisticMessage.time,
212
+ },
213
+ }
214
+ : s.chatrooms,
215
+ }
216
+ })
217
+
141
218
  const reader = res.body.getReader()
142
219
  const decoder = new TextDecoder()
143
220
  let buf = ''
@@ -220,13 +297,6 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
220
297
  return { streamingAgents: agents }
221
298
  })
222
299
  }
223
- try {
224
- const { currentChatroomId: cid } = get()
225
- if (cid) {
226
- const chatroom = await api<Chatroom>('GET', `/chatrooms/${cid}`)
227
- set((s) => ({ chatrooms: { ...s.chatrooms, [cid]: chatroom } }))
228
- }
229
- } catch { /* will catch on next WS push */ }
230
300
  } else if (event.t === 'done') {
231
301
  break
232
302
  }
@@ -236,31 +306,88 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
236
306
  }
237
307
  }
238
308
  } finally {
239
- set({ streaming: false, streamingAgents: new Map() })
240
- try {
241
- const { currentChatroomId: cid } = get()
242
- if (cid) {
243
- const chatroom = await api<Chatroom>('GET', `/chatrooms/${cid}`)
244
- set((s) => ({ chatrooms: { ...s.chatrooms, [cid]: chatroom } }))
309
+ if (started) {
310
+ set({ streaming: false, streamingAgents: new Map() })
311
+ try {
312
+ const chatroom = await api<Chatroom>('GET', `/chatrooms/${targetChatroomId}`)
313
+ set((s) => ({ chatrooms: { ...s.chatrooms, [targetChatroomId]: chatroom } }))
314
+ } catch { /* ignore */ }
315
+
316
+ const nextQueued = get().shiftQueuedMessage()
317
+ if (nextQueued) {
318
+ if (get().currentChatroomId !== nextQueued.chatroomId) {
319
+ set((s) => ({ queuedMessages: [nextQueued, ...s.queuedMessages] }))
320
+ return
321
+ }
322
+ set({ pendingFiles: nextQueued.pendingFiles, replyingTo: nextQueued.replyingTo })
323
+ setTimeout(() => {
324
+ void get().sendMessage(nextQueued.text)
325
+ }, 100)
245
326
  }
246
- } catch { /* ignore */ }
327
+ }
247
328
  }
248
329
  },
249
330
 
250
331
  toggleReaction: async (messageId, emoji) => {
251
332
  const { currentChatroomId } = get()
252
333
  if (!currentChatroomId) return
253
- await api('POST', `/chatrooms/${currentChatroomId}/reactions`, { messageId, emoji })
254
- const chatroom = await api<Chatroom>('GET', `/chatrooms/${currentChatroomId}`)
255
- set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
334
+ const previous = get().chatrooms[currentChatroomId]
335
+ if (previous) {
336
+ set((s) => ({
337
+ chatrooms: {
338
+ ...s.chatrooms,
339
+ [currentChatroomId]: {
340
+ ...previous,
341
+ messages: previous.messages.map((message) => {
342
+ if (message.id !== messageId) return message
343
+ const existing = message.reactions.find((reaction) => reaction.emoji === emoji && reaction.reactorId === 'user')
344
+ return {
345
+ ...message,
346
+ reactions: existing
347
+ ? message.reactions.filter((reaction) => !(reaction.emoji === emoji && reaction.reactorId === 'user'))
348
+ : [...message.reactions, { emoji, reactorId: 'user', time: Date.now() }],
349
+ }
350
+ }),
351
+ },
352
+ },
353
+ }))
354
+ }
355
+ try {
356
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/reactions`, { messageId, emoji })
357
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
358
+ } catch {
359
+ if (previous) {
360
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: previous } }))
361
+ }
362
+ }
256
363
  },
257
364
 
258
365
  togglePin: async (messageId) => {
259
366
  const { currentChatroomId } = get()
260
367
  if (!currentChatroomId) return
261
- await api('POST', `/chatrooms/${currentChatroomId}/pins`, { messageId })
262
- const chatroom = await api<Chatroom>('GET', `/chatrooms/${currentChatroomId}`)
263
- set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
368
+ const previous = get().chatrooms[currentChatroomId]
369
+ if (previous) {
370
+ const pinnedMessageIds = previous.pinnedMessageIds || []
371
+ set((s) => ({
372
+ chatrooms: {
373
+ ...s.chatrooms,
374
+ [currentChatroomId]: {
375
+ ...previous,
376
+ pinnedMessageIds: pinnedMessageIds.includes(messageId)
377
+ ? pinnedMessageIds.filter((id) => id !== messageId)
378
+ : [...pinnedMessageIds, messageId],
379
+ },
380
+ },
381
+ }))
382
+ }
383
+ try {
384
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/pins`, { messageId })
385
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
386
+ } catch {
387
+ if (previous) {
388
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: previous } }))
389
+ }
390
+ }
264
391
  },
265
392
 
266
393
  addMember: async (agentId) => {
@@ -52,12 +52,26 @@ export interface ProviderInfo {
52
52
  name: string
53
53
  models: string[]
54
54
  defaultModels?: string[]
55
+ supportsModelDiscovery?: boolean
55
56
  requiresApiKey: boolean
56
57
  optionalApiKey?: boolean
57
58
  requiresEndpoint: boolean
58
59
  defaultEndpoint?: string
59
60
  }
60
61
 
62
+ export interface ProviderModelDiscoveryResult {
63
+ ok: boolean
64
+ providerId: string
65
+ providerName?: string
66
+ models: string[]
67
+ cached: boolean
68
+ fetchedAt: number
69
+ cacheTtlMs: number
70
+ supportsDiscovery: boolean
71
+ missingCredential?: boolean
72
+ message?: string
73
+ }
74
+
61
75
  export interface Credential {
62
76
  id: string
63
77
  provider: string
@@ -78,6 +92,7 @@ export interface Session {
78
92
  credentialId?: string | null
79
93
  fallbackCredentialIds?: string[]
80
94
  apiEndpoint?: string | null
95
+ gatewayProfileId?: string | null
81
96
  claudeSessionId: string | null
82
97
  codexThreadId?: string | null
83
98
  opencodeSessionId?: string | null
@@ -105,13 +120,13 @@ export interface Session {
105
120
  sessionMaxAgeSec?: number | null
106
121
  sessionDailyResetAt?: string | null
107
122
  sessionResetTimezone?: string | null
108
- thinkingLevel?: 'minimal' | 'low' | 'medium' | 'high'
123
+ thinkingLevel?: 'minimal' | 'low' | 'medium' | 'high' | null
109
124
  browserProfileId?: string | null
110
- connectorThinkLevel?: 'minimal' | 'low' | 'medium' | 'high'
111
- connectorSessionScope?: 'main' | 'channel' | 'peer' | 'channel-peer' | 'thread'
112
- connectorReplyMode?: 'off' | 'first' | 'all'
113
- connectorThreadBinding?: 'off' | 'prefer' | 'strict'
114
- connectorGroupPolicy?: 'open' | 'mention' | 'reply-or-mention' | 'disabled'
125
+ connectorThinkLevel?: 'minimal' | 'low' | 'medium' | 'high' | null
126
+ connectorSessionScope?: 'main' | 'channel' | 'peer' | 'channel-peer' | 'thread' | null
127
+ connectorReplyMode?: 'off' | 'first' | 'all' | null
128
+ connectorThreadBinding?: 'off' | 'prefer' | 'strict' | null
129
+ connectorGroupPolicy?: 'open' | 'mention' | 'reply-or-mention' | 'disabled' | null
115
130
  connectorIdleTimeoutSec?: number | null
116
131
  connectorMaxAgeSec?: number | null
117
132
  mailbox?: MailboxEnvelope[] | null
@@ -482,6 +497,9 @@ export interface Agent {
482
497
  credentialId?: string | null
483
498
  fallbackCredentialIds?: string[]
484
499
  apiEndpoint?: string | null
500
+ gatewayProfileId?: string | null
501
+ routingStrategy?: AgentRoutingStrategy | null
502
+ routingTargets?: AgentRoutingTarget[]
485
503
  isOrchestrator?: boolean
486
504
  subAgentIds?: string[]
487
505
  plugins?: string[] // e.g. ['browser', 'memory'] — enabled plugin IDs
@@ -511,6 +529,8 @@ export interface Agent {
511
529
  sessionDailyResetAt?: string | null
512
530
  sessionResetTimezone?: string | null
513
531
  thinkingLevel?: 'minimal' | 'low' | 'medium' | 'high'
532
+ memoryScopeMode?: 'auto' | 'all' | 'global' | 'agent' | 'session' | 'project' | null
533
+ memoryTierPreference?: 'working' | 'durable' | 'archive' | 'blended' | null
514
534
  elevenLabsVoiceId?: string | null
515
535
  projectId?: string
516
536
  avatarSeed?: string
@@ -603,6 +623,11 @@ export interface Schedule {
603
623
  projectId?: string
604
624
  taskPrompt: string
605
625
  scheduleType: ScheduleType
626
+ action?: string
627
+ path?: string
628
+ command?: string
629
+ description?: string
630
+ frequency?: string
606
631
  cron?: string
607
632
  intervalMs?: number
608
633
  runAt?: number
@@ -611,7 +636,10 @@ export interface Schedule {
611
636
  status: ScheduleStatus
612
637
  linkedTaskId?: string | null
613
638
  runNumber?: number
639
+ createdByAgentId?: string | null
640
+ createdInSessionId?: string | null
614
641
  createdAt: number
642
+ updatedAt?: number
615
643
  }
616
644
 
617
645
  export type BrowserSessionStatus = 'active' | 'idle' | 'closed' | 'error'
@@ -1136,6 +1164,161 @@ export interface ProviderConfig {
1136
1164
  updatedAt: number
1137
1165
  }
1138
1166
 
1167
+ // --- Gateways ---
1168
+
1169
+ export type GatewayProvider = 'openclaw'
1170
+ export type GatewayHealthState = 'unknown' | 'healthy' | 'degraded' | 'offline' | 'pending'
1171
+
1172
+ export interface GatewayProfile {
1173
+ id: string
1174
+ name: string
1175
+ provider: GatewayProvider
1176
+ endpoint: string
1177
+ wsUrl?: string | null
1178
+ credentialId?: string | null
1179
+ status: GatewayHealthState
1180
+ notes?: string | null
1181
+ tags?: string[]
1182
+ lastError?: string | null
1183
+ lastCheckedAt?: number | null
1184
+ lastModelCount?: number | null
1185
+ discoveredHost?: string | null
1186
+ discoveredPort?: number | null
1187
+ isDefault?: boolean
1188
+ createdAt: number
1189
+ updatedAt: number
1190
+ }
1191
+
1192
+ export interface OpenClawNode {
1193
+ nodeId: string
1194
+ displayName?: string
1195
+ platform?: string
1196
+ version?: string
1197
+ coreVersion?: string
1198
+ uiVersion?: string
1199
+ deviceFamily?: string
1200
+ modelIdentifier?: string
1201
+ remoteIp?: string
1202
+ caps?: string[]
1203
+ commands?: string[]
1204
+ pathEnv?: string[]
1205
+ permissions?: string[]
1206
+ connectedAtMs?: number
1207
+ paired?: boolean
1208
+ connected?: boolean
1209
+ }
1210
+
1211
+ export interface OpenClawNodePairRequest {
1212
+ requestId: string
1213
+ nodeId?: string
1214
+ displayName?: string
1215
+ platform?: string
1216
+ remoteIp?: string
1217
+ createdAtMs?: number
1218
+ }
1219
+
1220
+ export interface OpenClawPairedDevice {
1221
+ deviceId: string
1222
+ displayName?: string
1223
+ role?: string
1224
+ remoteIp?: string
1225
+ platform?: string
1226
+ tokens?: Array<{ role?: string; scopes?: string[]; createdAtMs?: number; rotatedAtMs?: number; revokedAtMs?: number }>
1227
+ }
1228
+
1229
+ export interface OpenClawDevicePairRequest {
1230
+ requestId: string
1231
+ deviceId?: string
1232
+ displayName?: string
1233
+ role?: string
1234
+ platform?: string
1235
+ remoteIp?: string
1236
+ createdAtMs?: number
1237
+ }
1238
+
1239
+ export interface OpenClawPairingSnapshot {
1240
+ pending?: OpenClawDevicePairRequest[]
1241
+ paired?: OpenClawPairedDevice[]
1242
+ }
1243
+
1244
+ // --- Agent Routing / Packs ---
1245
+
1246
+ export type AgentRoutingStrategy = 'single' | 'balanced' | 'economy' | 'premium' | 'reasoning'
1247
+ export type AgentRoutingTargetRole = 'primary' | 'economy' | 'premium' | 'reasoning' | 'backup'
1248
+
1249
+ export interface AgentRoutingTarget {
1250
+ id: string
1251
+ label?: string
1252
+ role?: AgentRoutingTargetRole
1253
+ provider: ProviderType
1254
+ model: string
1255
+ credentialId?: string | null
1256
+ fallbackCredentialIds?: string[]
1257
+ apiEndpoint?: string | null
1258
+ gatewayProfileId?: string | null
1259
+ priority?: number
1260
+ }
1261
+
1262
+ export interface AgentPackEntry {
1263
+ id: string
1264
+ name: string
1265
+ description?: string
1266
+ provider: ProviderType
1267
+ model: string
1268
+ credentialId?: string | null
1269
+ fallbackCredentialIds?: string[]
1270
+ apiEndpoint?: string | null
1271
+ gatewayProfileId?: string | null
1272
+ routingStrategy?: AgentRoutingStrategy | null
1273
+ routingTargets?: AgentRoutingTarget[]
1274
+ tools?: string[]
1275
+ plugins?: string[]
1276
+ capabilities?: string[]
1277
+ soul?: string
1278
+ systemPrompt?: string
1279
+ }
1280
+
1281
+ export interface AgentPackManifest {
1282
+ schemaVersion: 1
1283
+ kind: 'swarmclaw-agent-pack'
1284
+ name: string
1285
+ description?: string
1286
+ exportedAt: number
1287
+ recommendedProviders?: ProviderType[]
1288
+ agents: AgentPackEntry[]
1289
+ }
1290
+
1291
+ // --- External Agents ---
1292
+
1293
+ export type ExternalAgentSourceType = 'codex' | 'claude' | 'opencode' | 'openclaw' | 'custom'
1294
+ export type ExternalAgentStatus = 'online' | 'idle' | 'offline' | 'stale'
1295
+
1296
+ export interface ExternalAgentRuntime {
1297
+ id: string
1298
+ name: string
1299
+ sourceType: ExternalAgentSourceType
1300
+ status: ExternalAgentStatus
1301
+ provider?: ProviderType | null
1302
+ model?: string | null
1303
+ workspace?: string | null
1304
+ transport?: 'http' | 'ws' | 'cli' | 'gateway' | 'custom' | null
1305
+ endpoint?: string | null
1306
+ agentId?: string | null
1307
+ gatewayProfileId?: string | null
1308
+ capabilities?: string[]
1309
+ labels?: string[]
1310
+ metadata?: Record<string, unknown> | null
1311
+ tokenStats?: {
1312
+ inputTokens?: number
1313
+ outputTokens?: number
1314
+ totalTokens?: number
1315
+ } | null
1316
+ lastHeartbeatAt?: number | null
1317
+ lastSeenAt?: number | null
1318
+ createdAt: number
1319
+ updatedAt: number
1320
+ }
1321
+
1139
1322
  // --- Skills ---
1140
1323
 
1141
1324
  export interface Skill {
@@ -1,13 +0,0 @@
1
- import { NextResponse } from 'next/server'
2
-
3
- function retiredResponse() {
4
- return new NextResponse('Mission controls are no longer supported.', { status: 410 })
5
- }
6
-
7
- export async function GET() {
8
- return retiredResponse()
9
- }
10
-
11
- export async function POST() {
12
- return retiredResponse()
13
- }