@swarmclawai/swarmclaw 1.2.8 → 1.3.0

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 (214) hide show
  1. package/README.md +39 -6
  2. package/package.json +2 -2
  3. package/src/app/agents/[id]/page.tsx +1 -18
  4. package/src/app/api/activity/route.ts +9 -23
  5. package/src/app/api/agents/route.ts +17 -1
  6. package/src/app/api/agents/thread-route.test.ts +0 -1
  7. package/src/app/api/approvals/route.test.ts +6 -22
  8. package/src/app/api/approvals/route.ts +13 -5
  9. package/src/app/api/connectors/route.ts +2 -2
  10. package/src/app/api/credentials/[id]/route.ts +2 -0
  11. package/src/app/api/credentials/route.ts +4 -1
  12. package/src/app/api/goals/[id]/route.ts +28 -0
  13. package/src/app/api/goals/route.ts +33 -0
  14. package/src/app/api/portability/export/route.ts +8 -0
  15. package/src/app/api/portability/import/route.test.ts +80 -0
  16. package/src/app/api/portability/import/route.ts +28 -0
  17. package/src/app/api/protocols/templates/[id]/route.ts +2 -1
  18. package/src/app/api/protocols/templates/route.ts +2 -1
  19. package/src/app/api/settings/route.ts +13 -2
  20. package/src/app/api/wallets/[id]/route.ts +15 -157
  21. package/src/app/api/wallets/generate/route.ts +22 -0
  22. package/src/app/api/wallets/route.test.ts +147 -0
  23. package/src/app/api/wallets/route.ts +13 -95
  24. package/src/app/autonomy/page.tsx +2 -57
  25. package/src/app/home/page.tsx +3 -0
  26. package/src/app/protocols/page.tsx +2 -21
  27. package/src/app/settings/page.tsx +0 -9
  28. package/src/app/wallets/page.tsx +105 -5
  29. package/src/cli/index.js +32 -33
  30. package/src/cli/spec.js +26 -27
  31. package/src/components/agents/agent-sheet.tsx +2 -40
  32. package/src/components/agents/inspector-panel.tsx +0 -83
  33. package/src/components/chat/chat-card.tsx +0 -31
  34. package/src/components/chat/message-bubble.tsx +1 -108
  35. package/src/components/connectors/connector-sheet.tsx +25 -1
  36. package/src/components/layout/sidebar-rail.tsx +6 -10
  37. package/src/components/projects/project-detail.tsx +3 -35
  38. package/src/components/projects/tabs/overview-tab.tsx +3 -59
  39. package/src/components/projects/tabs/work-tab.tsx +7 -77
  40. package/src/components/protocols/structured-session-launcher.tsx +1 -22
  41. package/src/components/shared/connector-platform-icon.tsx +1 -0
  42. package/src/components/tasks/task-card.tsx +4 -34
  43. package/src/components/tasks/task-sheet.tsx +6 -36
  44. package/src/components/wallets/wallet-list.tsx +150 -0
  45. package/src/lib/app/navigation.test.ts +0 -13
  46. package/src/lib/app/navigation.ts +2 -7
  47. package/src/lib/app/view-constants.ts +14 -19
  48. package/src/lib/server/activity/activity-log.ts +16 -1
  49. package/src/lib/server/agents/agent-service.ts +24 -11
  50. package/src/lib/server/agents/agent-thread-session.ts +0 -1
  51. package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
  52. package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
  53. package/src/lib/server/agents/delegation-jobs.ts +0 -25
  54. package/src/lib/server/agents/main-agent-loop.ts +1 -49
  55. package/src/lib/server/agents/subagent-runtime.ts +0 -1
  56. package/src/lib/server/approval-match.ts +14 -85
  57. package/src/lib/server/approvals/approval-hooks.ts +81 -0
  58. package/src/lib/server/approvals.test.ts +6 -6
  59. package/src/lib/server/approvals.ts +11 -6
  60. package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
  61. package/src/lib/server/builtin-extensions.ts +0 -2
  62. package/src/lib/server/capability-router.test.ts +0 -2
  63. package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
  64. package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
  65. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
  66. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
  67. package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
  68. package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
  69. package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
  70. package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
  71. package/src/lib/server/chat-execution/message-classifier.ts +1 -16
  72. package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
  73. package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
  74. package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
  75. package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
  76. package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
  77. package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
  78. package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
  79. package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
  80. package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
  81. package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
  82. package/src/lib/server/chats/chat-session-service.ts +3 -5
  83. package/src/lib/server/connectors/connector-inbound.ts +0 -1
  84. package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
  85. package/src/lib/server/connectors/connector-service.ts +39 -9
  86. package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
  87. package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
  88. package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
  89. package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
  90. package/src/lib/server/connectors/swarmdock-tasks.ts +127 -0
  91. package/src/lib/server/connectors/swarmdock.ts +285 -0
  92. package/src/lib/server/execution-brief.test.ts +2 -25
  93. package/src/lib/server/execution-brief.ts +30 -35
  94. package/src/lib/server/execution-engine/task-attempt.ts +0 -1
  95. package/src/lib/server/goals/goal-repository.ts +19 -0
  96. package/src/lib/server/goals/goal-service.ts +143 -0
  97. package/src/lib/server/persistence/storage-context.ts +0 -5
  98. package/src/lib/server/portability/export.ts +109 -0
  99. package/src/lib/server/portability/import.ts +159 -0
  100. package/src/lib/server/protocols/protocol-normalization.ts +0 -4
  101. package/src/lib/server/protocols/protocol-queries.ts +0 -6
  102. package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
  103. package/src/lib/server/protocols/protocol-service.ts +0 -1
  104. package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
  105. package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
  106. package/src/lib/server/protocols/protocol-swarm.ts +0 -2
  107. package/src/lib/server/protocols/protocol-types.ts +0 -2
  108. package/src/lib/server/provider-health.ts +0 -9
  109. package/src/lib/server/runtime/daemon-state/core.ts +0 -9
  110. package/src/lib/server/runtime/daemon-state.test.ts +0 -35
  111. package/src/lib/server/runtime/heartbeat-service.ts +3 -23
  112. package/src/lib/server/runtime/queue/core.ts +11 -33
  113. package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
  114. package/src/lib/server/runtime/scheduler.ts +0 -13
  115. package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
  116. package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
  117. package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
  118. package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
  119. package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
  120. package/src/lib/server/session-tools/crud.ts +0 -14
  121. package/src/lib/server/session-tools/delegate.ts +0 -4
  122. package/src/lib/server/session-tools/index.ts +0 -4
  123. package/src/lib/server/session-tools/team-context.ts +0 -3
  124. package/src/lib/server/storage-normalization.ts +13 -0
  125. package/src/lib/server/storage.ts +75 -45
  126. package/src/lib/server/tasks/task-checkout.ts +59 -0
  127. package/src/lib/server/tasks/task-lifecycle.ts +2 -0
  128. package/src/lib/server/tasks/task-route-service.ts +4 -26
  129. package/src/lib/server/tasks/task-service.ts +0 -7
  130. package/src/lib/server/tool-aliases.ts +0 -1
  131. package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
  132. package/src/lib/server/tool-capability-policy.ts +0 -2
  133. package/src/lib/server/tool-planning.ts +0 -12
  134. package/src/lib/server/universal-tool-access.ts +0 -1
  135. package/src/lib/server/usage/cost-rollup.ts +124 -0
  136. package/src/lib/server/usage/usage-repository.ts +6 -0
  137. package/src/lib/server/wallets/wallet-crypto.ts +33 -0
  138. package/src/lib/server/wallets/wallet-repository.ts +24 -0
  139. package/src/lib/server/wallets/wallet-service.ts +119 -0
  140. package/src/lib/server/working-state/extraction.ts +8 -42
  141. package/src/lib/server/working-state/normalization.ts +10 -103
  142. package/src/lib/server/working-state/service.ts +12 -21
  143. package/src/lib/strip-internal-metadata.test.ts +1 -1
  144. package/src/lib/strip-internal-metadata.ts +1 -1
  145. package/src/lib/tool-definitions.ts +0 -1
  146. package/src/lib/validation/schemas.ts +36 -32
  147. package/src/lib/validation/server-schemas.ts +35 -0
  148. package/src/stores/slices/data-slice.ts +5 -1
  149. package/src/stores/slices/ui-slice.ts +0 -4
  150. package/src/types/agent.ts +10 -84
  151. package/src/types/app-settings.ts +6 -2
  152. package/src/types/approval.ts +3 -2
  153. package/src/types/connector.ts +1 -0
  154. package/src/types/goal.ts +30 -0
  155. package/src/types/index.ts +2 -1
  156. package/src/types/message.ts +0 -1
  157. package/src/types/misc.ts +2 -4
  158. package/src/types/protocol.ts +0 -2
  159. package/src/types/run.ts +0 -3
  160. package/src/types/session.ts +1 -51
  161. package/src/types/swarmdock.ts +29 -0
  162. package/src/types/task.ts +9 -3
  163. package/src/types/working-state.ts +2 -9
  164. package/src/views/settings/section-runtime-loop.tsx +0 -14
  165. package/src/app/api/canvas/[sessionId]/route.ts +0 -35
  166. package/src/app/api/missions/[id]/actions/route.ts +0 -31
  167. package/src/app/api/missions/[id]/events/route.ts +0 -14
  168. package/src/app/api/missions/[id]/route.ts +0 -10
  169. package/src/app/api/missions/route.test.ts +0 -244
  170. package/src/app/api/missions/route.ts +0 -57
  171. package/src/app/api/wallets/[id]/approve/route.ts +0 -79
  172. package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
  173. package/src/app/api/wallets/[id]/send/route.ts +0 -113
  174. package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
  175. package/src/app/missions/[id]/page.tsx +0 -3
  176. package/src/app/missions/page.tsx +0 -685
  177. package/src/components/canvas/canvas-panel.tsx +0 -267
  178. package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
  179. package/src/components/wallets/wallet-panel.tsx +0 -1010
  180. package/src/components/wallets/wallet-section.tsx +0 -260
  181. package/src/features/missions/queries.ts +0 -23
  182. package/src/lib/canvas-content.test.ts +0 -360
  183. package/src/lib/canvas-content.ts +0 -198
  184. package/src/lib/server/canvas-content.test.ts +0 -32
  185. package/src/lib/server/canvas-content.ts +0 -6
  186. package/src/lib/server/ethereum.ts +0 -591
  187. package/src/lib/server/evm-swap.ts +0 -476
  188. package/src/lib/server/missions/mission-intent.test.ts +0 -63
  189. package/src/lib/server/missions/mission-intent.ts +0 -569
  190. package/src/lib/server/missions/mission-repository.ts +0 -74
  191. package/src/lib/server/missions/mission-service/actions.ts +0 -6
  192. package/src/lib/server/missions/mission-service/bindings.ts +0 -9
  193. package/src/lib/server/missions/mission-service/context.ts +0 -4
  194. package/src/lib/server/missions/mission-service/core.ts +0 -2271
  195. package/src/lib/server/missions/mission-service/queries.ts +0 -12
  196. package/src/lib/server/missions/mission-service/recovery.ts +0 -5
  197. package/src/lib/server/missions/mission-service/ticks.ts +0 -9
  198. package/src/lib/server/missions/mission-service.test.ts +0 -888
  199. package/src/lib/server/missions/mission-service.ts +0 -6
  200. package/src/lib/server/session-tools/canvas.ts +0 -105
  201. package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
  202. package/src/lib/server/session-tools/wallet.ts +0 -1287
  203. package/src/lib/server/solana.ts +0 -327
  204. package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
  205. package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
  206. package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
  207. package/src/lib/server/wallet/wallet-service.test.ts +0 -81
  208. package/src/lib/server/wallet/wallet-service.ts +0 -225
  209. package/src/lib/wallet/wallet-transactions.test.ts +0 -75
  210. package/src/lib/wallet/wallet-transactions.ts +0 -43
  211. package/src/lib/wallet/wallet.test.ts +0 -333
  212. package/src/lib/wallet/wallet.ts +0 -183
  213. package/src/types/mission.ts +0 -185
  214. package/src/views/settings/section-wallets.tsx +0 -35
@@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
4
4
  import { useRouter, useSearchParams } from 'next/navigation'
5
5
  import { useAgentsQuery } from '@/features/agents/queries'
6
6
  import { useChatroomsQuery } from '@/features/chatrooms/queries'
7
- import { useMissionsQuery } from '@/features/missions/queries'
8
7
  import {
9
8
  useCreateProtocolRunMutation,
10
9
  useDeleteProtocolTemplateMutation,
@@ -21,7 +20,6 @@ import { timeAgo } from '@/lib/time-format'
21
20
  import type {
22
21
  BoardTask,
23
22
  Chatroom,
24
- Mission,
25
23
  ProtocolRun,
26
24
  ProtocolRunEvent,
27
25
  ProtocolStepDefinition,
@@ -33,7 +31,6 @@ type ProtocolRunDetail = {
33
31
  template: ProtocolTemplate | null
34
32
  transcript: Chatroom | null
35
33
  parentChatroom: Chatroom | null
36
- linkedMission: Mission | null
37
34
  linkedTask: BoardTask | null
38
35
  events: ProtocolRunEvent[]
39
36
  }
@@ -153,7 +150,6 @@ export default function ProtocolsPage() {
153
150
  facilitatorAgentId: '',
154
151
  participantAgentIds: [] as string[],
155
152
  parentChatroomId: '',
156
- missionId: '',
157
153
  taskId: '',
158
154
  autoStart: true,
159
155
  })
@@ -162,7 +158,6 @@ export default function ProtocolsPage() {
162
158
  const runsQuery = useProtocolRunsQuery({ limit: 120 })
163
159
  const agentsQuery = useAgentsQuery()
164
160
  const chatroomsQuery = useChatroomsQuery()
165
- const missionsQuery = useMissionsQuery({ limit: 80 })
166
161
  const tasksQuery = useTasksQuery({ includeArchived: true })
167
162
  const detailQuery = useProtocolRunDetailQuery(selectedRunId, { enabled: Boolean(selectedRunId) })
168
163
  const createRunMutation = useCreateProtocolRunMutation()
@@ -174,14 +169,12 @@ export default function ProtocolsPage() {
174
169
  const detail = detailQuery.data ?? null
175
170
  const agents = agentsQuery.data ?? {}
176
171
  const chatrooms = chatroomsQuery.data ?? {}
177
- const missions = missionsQuery.data ?? []
178
172
  const tasks = tasksQuery.data ?? {}
179
173
  const loading = (
180
174
  templatesQuery.isLoading
181
175
  || runsQuery.isLoading
182
176
  || agentsQuery.isLoading
183
177
  || chatroomsQuery.isLoading
184
- || missionsQuery.isLoading
185
178
  || tasksQuery.isLoading
186
179
  )
187
180
  const detailLoading = detailQuery.isLoading || detailQuery.isFetching
@@ -190,7 +183,6 @@ export default function ProtocolsPage() {
190
183
  runsQuery.error,
191
184
  agentsQuery.error,
192
185
  chatroomsQuery.error,
193
- missionsQuery.error,
194
186
  tasksQuery.error,
195
187
  detailQuery.error,
196
188
  ].find(Boolean)
@@ -237,7 +229,6 @@ export default function ProtocolsPage() {
237
229
  participantAgentIds: form.participantAgentIds,
238
230
  facilitatorAgentId: form.facilitatorAgentId || null,
239
231
  parentChatroomId: form.parentChatroomId || null,
240
- missionId: form.missionId || null,
241
232
  taskId: form.taskId || null,
242
233
  autoStart: form.autoStart,
243
234
  config: {
@@ -364,7 +355,7 @@ export default function ProtocolsPage() {
364
355
  </div>
365
356
  <h1 className="mt-4 font-display text-[34px] font-700 tracking-[-0.03em] text-text">Bounded Collaboration Runs</h1>
366
357
  <p className="mt-3 max-w-[720px] text-[15px] leading-relaxed text-text-3/72">
367
- Start structured sessions from chats, chatrooms, tasks, missions, or schedules. Runs stay temporary and bounded, while templates remain reusable for the next time you need them.
358
+ Start structured sessions from chats, chatrooms, tasks, or schedules. Runs stay temporary and bounded, while templates remain reusable for the next time you need them.
368
359
  </p>
369
360
  </div>
370
361
  <div className="w-full max-w-[520px] rounded-[20px] border border-white/[0.06] bg-surface/70 p-4">
@@ -372,7 +363,7 @@ export default function ProtocolsPage() {
372
363
  <div>
373
364
  <div className="text-[11px] font-700 uppercase tracking-[0.12em] text-text-3/55">Launch and Templates</div>
374
365
  <div className="mt-1 text-[13px] leading-relaxed text-text-3/68">
375
- Start from here when you need a blank run. Normal use should start from the chat, task, mission, or chatroom you are already in.
366
+ Start from here when you need a blank run. Normal use should start from the chat, task, or chatroom you are already in.
376
367
  </div>
377
368
  </div>
378
369
  <div className="flex flex-wrap gap-2">
@@ -471,16 +462,6 @@ export default function ProtocolsPage() {
471
462
  <option key={chatroom.id} value={chatroom.id}>{chatroom.name}</option>
472
463
  ))}
473
464
  </select>
474
- <select
475
- value={form.missionId}
476
- onChange={(event) => setForm((current) => ({ ...current, missionId: event.target.value }))}
477
- className="rounded-[12px] border border-white/[0.06] bg-white/[0.04] px-3 py-2.5 text-[14px] text-text outline-none"
478
- >
479
- <option value="">No linked mission</option>
480
- {missions.map((mission) => (
481
- <option key={mission.id} value={mission.id}>{mission.objective}</option>
482
- ))}
483
- </select>
484
465
  <select
485
466
  value={form.taskId}
486
467
  onChange={(event) => setForm((current) => ({ ...current, taskId: event.target.value }))}
@@ -11,7 +11,6 @@ import { ThemeSection } from '@/views/settings/section-theme'
11
11
  import { RuntimeLoopSection } from '@/views/settings/section-runtime-loop'
12
12
  import { SupervisorReflectionSection } from '@/views/settings/section-supervisor-reflection'
13
13
  import { CapabilityPolicySection } from '@/views/settings/section-capability-policy'
14
- import { WalletsSection } from '@/views/settings/section-wallets'
15
14
  import { StorageSection } from '@/views/settings/section-storage'
16
15
  import { VoiceSection } from '@/views/settings/section-voice'
17
16
  import { WebSearchSection } from '@/views/settings/section-web-search'
@@ -149,14 +148,6 @@ export default function SettingsRoute() {
149
148
  keywords: ['storage', 'uploads', 'disk', 'cleanup', 'files'],
150
149
  render: () => <StorageSection {...sectionProps} />,
151
150
  },
152
- {
153
- id: 'wallets',
154
- tabId: 'general',
155
- title: 'Wallets',
156
- description: 'Control global wallet approval behavior and auto-execution defaults.',
157
- keywords: ['wallet', 'wallets', 'approval', 'approvals', 'crypto', 'send'],
158
- render: () => <WalletsSection {...sectionProps} />,
159
- },
160
151
  {
161
152
  id: 'theme',
162
153
  tabId: 'appearance',
@@ -1,12 +1,112 @@
1
1
  'use client'
2
2
 
3
- import { WalletPanel } from '@/components/wallets/wallet-panel'
4
- import { MainContent } from '@/components/layout/main-content'
3
+ import { useEffect, useState } from 'react'
4
+ import { useAppStore } from '@/stores/use-app-store'
5
+ import { WalletList } from '@/components/wallets/wallet-list'
6
+ import { api } from '@/lib/app/api-client'
7
+ import type { SafeWallet } from '@/types'
5
8
 
6
9
  export default function WalletsPage() {
10
+ const agents = useAppStore((s) => s.agents)
11
+ const loadAgents = useAppStore((s) => s.loadAgents)
12
+ const loadWallets = useAppStore((s) => s.loadWallets)
13
+ const [generating, setGenerating] = useState(false)
14
+ const [showPicker, setShowPicker] = useState(false)
15
+ const [error, setError] = useState<string | null>(null)
16
+
17
+ useEffect(() => {
18
+ loadAgents()
19
+ loadWallets()
20
+ }, [loadAgents, loadWallets])
21
+
22
+ const agentList = Object.values(agents)
23
+
24
+ const handleGenerate = async (agentId?: string) => {
25
+ const targetId = agentId || agentList[0]?.id
26
+ if (!targetId) {
27
+ setError('Create an agent first')
28
+ setTimeout(() => setError(null), 3000)
29
+ return
30
+ }
31
+ setGenerating(true)
32
+ setShowPicker(false)
33
+ setError(null)
34
+ try {
35
+ await api<SafeWallet>('POST', '/wallets/generate', { agentId: targetId })
36
+ loadWallets()
37
+ } catch (err) {
38
+ setError(err instanceof Error ? err.message : 'Failed to generate wallet')
39
+ setTimeout(() => setError(null), 4000)
40
+ } finally {
41
+ setGenerating(false)
42
+ }
43
+ }
44
+
7
45
  return (
8
- <MainContent>
9
- <WalletPanel />
10
- </MainContent>
46
+ <div className="flex-1 flex flex-col h-full">
47
+ <div className="flex items-center px-6 pt-5 pb-3 shrink-0">
48
+ <h2 className="font-display text-[14px] font-600 text-text-2 tracking-[-0.01em] capitalize flex-1">
49
+ Wallets
50
+ </h2>
51
+ <div className="relative">
52
+ <button
53
+ onClick={() => {
54
+ if (agentList.length <= 1) {
55
+ handleGenerate()
56
+ } else {
57
+ setShowPicker(!showPicker)
58
+ }
59
+ }}
60
+ disabled={generating}
61
+ className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-[8px] text-[11px] font-600 text-accent-bright bg-accent-soft hover:bg-accent-bright/15 transition-all cursor-pointer disabled:opacity-50"
62
+ style={{ fontFamily: 'inherit' }}
63
+ >
64
+ {generating ? (
65
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" className="animate-spin">
66
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
67
+ </svg>
68
+ ) : (
69
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
70
+ <line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
71
+ </svg>
72
+ )}
73
+ {generating ? 'Generating...' : 'Generate Wallet'}
74
+ </button>
75
+
76
+ {/* Agent picker dropdown */}
77
+ {showPicker && (
78
+ <>
79
+ <div className="fixed inset-0 z-40" onClick={() => setShowPicker(false)} />
80
+ <div className="absolute right-0 top-full mt-1 z-50 w-56 rounded-[12px] bg-surface border border-white/[0.08] shadow-xl overflow-hidden">
81
+ <div className="px-3 py-2 border-b border-white/[0.06]">
82
+ <span className="text-[11px] font-600 text-text-3">Select Agent</span>
83
+ </div>
84
+ <div className="max-h-48 overflow-y-auto py-1">
85
+ {agentList.map((agent) => (
86
+ <button
87
+ key={agent.id}
88
+ onClick={() => handleGenerate(agent.id)}
89
+ className="w-full text-left px-3 py-2 flex items-center gap-2 hover:bg-white/[0.04] transition-colors cursor-pointer"
90
+ style={{ fontFamily: 'inherit' }}
91
+ >
92
+ <span className="text-[14px]">{agent.emoji || '🤖'}</span>
93
+ <span className="text-[12px] font-600 text-text truncate">{agent.name}</span>
94
+ </button>
95
+ ))}
96
+ </div>
97
+ </div>
98
+ </>
99
+ )}
100
+ </div>
101
+ </div>
102
+
103
+ {error && (
104
+ <div className="mx-6 mb-2 px-3 py-2 rounded-[10px] bg-red-500/10 border border-red-500/20 text-[12px] text-red-400 font-600">
105
+ {error}
106
+ </div>
107
+ )}
108
+
109
+ <WalletList />
110
+ </div>
11
111
  )
12
112
  }
package/src/cli/index.js CHANGED
@@ -105,14 +105,6 @@ const COMMAND_GROUPS = [
105
105
  cmd('moderate', 'POST', '/chatrooms/:id/moderate', 'Run moderation action on a chatroom', { expectsJsonBody: true }),
106
106
  ],
107
107
  },
108
- {
109
- name: 'canvas',
110
- description: 'Read/update per-session canvas content',
111
- commands: [
112
- cmd('get', 'GET', '/canvas/:sessionId', 'Get current canvas content for a session'),
113
- cmd('set', 'POST', '/canvas/:sessionId', 'Set/clear canvas content for a session', { expectsJsonBody: true }),
114
- ],
115
- },
116
108
  {
117
109
  name: 'connectors',
118
110
  description: 'Manage chat connectors',
@@ -307,16 +299,7 @@ const COMMAND_GROUPS = [
307
299
  cmd('get', 'GET', '/memory-images/:filename', 'Download memory image by filename', { responseType: 'binary' }),
308
300
  ],
309
301
  },
310
- {
311
- name: 'missions',
312
- description: 'Inspect and control durable missions',
313
- commands: [
314
- cmd('list', 'GET', '/missions', 'List missions (use --query status=, --query phase=, --query source=, --query sessionId=, --query agentId=, --query projectId=)'),
315
- cmd('get', 'GET', '/missions/:id', 'Get mission detail by id'),
316
- cmd('events', 'GET', '/missions/:id/events', 'Get mission event timeline', { expectsQueryHint: true }),
317
- cmd('action', 'POST', '/missions/:id/actions', 'Run a mission control action (resume, replan, retry_verification, wait, cancel)', { expectsJsonBody: true }),
318
- ],
319
- },
302
+
320
303
  {
321
304
  name: 'notifications',
322
305
  description: 'Manage in-app notifications',
@@ -696,21 +679,6 @@ const COMMAND_GROUPS = [
696
679
  }),
697
680
  ],
698
681
  },
699
- {
700
- name: 'wallets',
701
- description: 'Manage agent wallets and wallet transactions',
702
- commands: [
703
- cmd('list', 'GET', '/wallets', 'List wallets'),
704
- cmd('get', 'GET', '/wallets/:id', 'Get wallet by id'),
705
- cmd('create', 'POST', '/wallets', 'Create wallet', { expectsJsonBody: true }),
706
- cmd('update', 'PATCH', '/wallets/:id', 'Update wallet settings', { expectsJsonBody: true }),
707
- cmd('delete', 'DELETE', '/wallets/:id', 'Delete wallet'),
708
- cmd('send', 'POST', '/wallets/:id/send', 'Send funds from wallet', { expectsJsonBody: true }),
709
- cmd('approve', 'POST', '/wallets/:id/approve', 'Approve or deny a pending wallet transaction', { expectsJsonBody: true }),
710
- cmd('transactions', 'GET', '/wallets/:id/transactions', 'List wallet transactions'),
711
- cmd('balance-history', 'GET', '/wallets/:id/balance-history', 'Get wallet balance history'),
712
- ],
713
- },
714
682
  {
715
683
  name: 'upload',
716
684
  description: 'Upload raw file/blob',
@@ -769,6 +737,37 @@ const COMMAND_GROUPS = [
769
737
  cmd('history', 'GET', '/webhooks/:id/history', 'Get webhook delivery history'),
770
738
  ],
771
739
  },
740
+ {
741
+ name: 'portability',
742
+ description: 'Export and import agent configurations',
743
+ commands: [
744
+ cmd('export', 'GET', '/portability/export', 'Export agents, skills, and schedules as a portable JSON manifest'),
745
+ cmd('import', 'POST', '/portability/import', 'Import a portable JSON manifest', { expectsJsonBody: true }),
746
+ ],
747
+ },
748
+ {
749
+ name: 'wallets',
750
+ description: 'Manage agent wallets',
751
+ commands: [
752
+ cmd('list', 'GET', '/wallets', 'List wallets'),
753
+ cmd('get', 'GET', '/wallets/:id', 'Get wallet by id'),
754
+ cmd('create', 'POST', '/wallets', 'Create a wallet', { expectsJsonBody: true }),
755
+ cmd('generate', 'POST', '/wallets/generate', 'Generate a new wallet for an agent', { expectsJsonBody: true }),
756
+ cmd('update', 'PATCH', '/wallets/:id', 'Update wallet settings', { expectsJsonBody: true }),
757
+ cmd('delete', 'DELETE', '/wallets/:id', 'Delete a wallet'),
758
+ ],
759
+ },
760
+ {
761
+ name: 'goals',
762
+ description: 'Manage goal hierarchy',
763
+ commands: [
764
+ cmd('list', 'GET', '/goals', 'List goals'),
765
+ cmd('get', 'GET', '/goals/:id', 'Get goal by id'),
766
+ cmd('create', 'POST', '/goals', 'Create a goal', { expectsJsonBody: true }),
767
+ cmd('update', 'PATCH', '/goals/:id', 'Update a goal', { expectsJsonBody: true }),
768
+ cmd('delete', 'DELETE', '/goals/:id', 'Delete a goal'),
769
+ ],
770
+ },
772
771
  ]
773
772
 
774
773
  const GROUP_MAP = new Map(COMMAND_GROUPS.map((group) => [group.name, group]))
package/src/cli/spec.js CHANGED
@@ -59,13 +59,6 @@ const COMMAND_GROUPS = {
59
59
  pin: { description: 'Toggle pin on a chatroom message', method: 'POST', path: '/chatrooms/:id/pins', params: ['id'] },
60
60
  },
61
61
  },
62
- canvas: {
63
- description: 'Session canvas content',
64
- commands: {
65
- get: { description: 'Get current canvas content for a session', method: 'GET', path: '/canvas/:sessionId', params: ['sessionId'] },
66
- set: { description: 'Set/clear canvas content for a session', method: 'POST', path: '/canvas/:sessionId', params: ['sessionId'] },
67
- },
68
- },
69
62
  connectors: {
70
63
  description: 'Manage chat connectors',
71
64
  commands: {
@@ -214,15 +207,7 @@ const COMMAND_GROUPS = {
214
207
  clear: { description: 'Clear log file', method: 'DELETE', path: '/logs' },
215
208
  },
216
209
  },
217
- missions: {
218
- description: 'Inspect and control durable missions',
219
- commands: {
220
- list: { description: 'List missions (supports --query status=,phase=,source=,sessionId=,agentId=,projectId=)', method: 'GET', path: '/missions' },
221
- get: { description: 'Get mission detail by id', method: 'GET', path: '/missions/:id', params: ['id'] },
222
- events: { description: 'Get mission event timeline', method: 'GET', path: '/missions/:id/events', params: ['id'] },
223
- action: { description: 'Run a mission control action (resume, replan, retry_verification, wait, cancel)', method: 'POST', path: '/missions/:id/actions', params: ['id'] },
224
- },
225
- },
210
+
226
211
  memory: {
227
212
  description: 'Agent memory entries',
228
213
  commands: {
@@ -526,24 +511,38 @@ const COMMAND_GROUPS = {
526
511
  events: { description: 'Get run event history by run id', method: 'GET', path: '/runs/:id/events', params: ['id'] },
527
512
  },
528
513
  },
514
+ webhooks: {
515
+ description: 'Inbound webhook triggers',
516
+ commands: {
517
+ trigger: { description: 'Trigger webhook by id', method: 'POST', path: '/webhooks/:id', params: ['id'], waitable: true },
518
+ },
519
+ },
520
+ portability: {
521
+ description: 'Export and import agent configurations',
522
+ commands: {
523
+ export: { description: 'Export agents, skills, and schedules as a portable JSON manifest', method: 'GET', path: '/portability/export' },
524
+ import: { description: 'Import a portable JSON manifest', method: 'POST', path: '/portability/import', body: true },
525
+ },
526
+ },
529
527
  wallets: {
530
- description: 'Agent wallet operations',
528
+ description: 'Manage agent wallets',
531
529
  commands: {
532
530
  list: { description: 'List wallets', method: 'GET', path: '/wallets' },
533
531
  get: { description: 'Get wallet by id', method: 'GET', path: '/wallets/:id', params: ['id'] },
534
- create: { description: 'Create wallet', method: 'POST', path: '/wallets' },
535
- update: { description: 'Update wallet settings', method: 'PATCH', path: '/wallets/:id', params: ['id'] },
536
- delete: { description: 'Delete wallet', method: 'DELETE', path: '/wallets/:id', params: ['id'] },
537
- send: { description: 'Send funds from wallet', method: 'POST', path: '/wallets/:id/send', params: ['id'] },
538
- approve: { description: 'Approve or deny pending wallet transaction', method: 'POST', path: '/wallets/:id/approve', params: ['id'] },
539
- transactions: { description: 'List wallet transactions', method: 'GET', path: '/wallets/:id/transactions', params: ['id'] },
540
- 'balance-history': { description: 'Get wallet balance history', method: 'GET', path: '/wallets/:id/balance-history', params: ['id'] },
532
+ create: { description: 'Create a wallet', method: 'POST', path: '/wallets' },
533
+ generate: { description: 'Generate a new wallet for an agent', method: 'POST', path: '/wallets/generate', body: true },
534
+ update: { description: 'Update wallet settings', method: 'PATCH', path: '/wallets/:id', params: ['id'], body: true },
535
+ delete: { description: 'Delete a wallet', method: 'DELETE', path: '/wallets/:id', params: ['id'] },
541
536
  },
542
537
  },
543
- webhooks: {
544
- description: 'Inbound webhook triggers',
538
+ goals: {
539
+ description: 'Manage goal hierarchy',
545
540
  commands: {
546
- trigger: { description: 'Trigger webhook by id', method: 'POST', path: '/webhooks/:id', params: ['id'], waitable: true },
541
+ list: { description: 'List goals', method: 'GET', path: '/goals' },
542
+ get: { description: 'Get goal by id', method: 'GET', path: '/goals/:id', params: ['id'] },
543
+ create: { description: 'Create a goal', method: 'POST', path: '/goals' },
544
+ update: { description: 'Update a goal', method: 'PATCH', path: '/goals/:id', params: ['id'], body: true },
545
+ delete: { description: 'Delete a goal', method: 'DELETE', path: '/goals/:id', params: ['id'] },
547
546
  },
548
547
  },
549
548
  }
@@ -10,8 +10,7 @@ import { sleep } from '@/lib/shared-utils'
10
10
  import { BottomSheet } from '@/components/shared/bottom-sheet'
11
11
  import { toast } from 'sonner'
12
12
  import { ModelCombobox } from '@/components/shared/model-combobox'
13
- import type { ProviderType, ClaudeSkill, AgentWallet, AgentPackManifest, AgentRoutingStrategy, AgentRoutingTarget } from '@/types'
14
- import { WalletSection } from '@/components/wallets/wallet-section'
13
+ import type { ProviderType, ClaudeSkill, AgentPackManifest, AgentRoutingStrategy, AgentRoutingTarget } from '@/types'
15
14
  import { AVAILABLE_TOOLS, PLATFORM_TOOLS } from '@/lib/tool-definitions'
16
15
  import { NATIVE_CAPABILITY_PROVIDER_IDS, NON_LANGGRAPH_PROVIDER_IDS, WORKER_ONLY_PROVIDER_IDS } from '@/lib/provider-sets'
17
16
  import { isOrchestratorProviderEligible } from '@/lib/orchestrator-config'
@@ -49,14 +48,6 @@ const AUTO_SYNC_MODEL_PROVIDER_IDS = new Set<ProviderType>([
49
48
  const CONNECTION_TEST_TIMEOUT_MS = 40_000
50
49
  type AgentProviderId = string
51
50
 
52
- type SafeAgentWallet = Omit<AgentWallet, 'encryptedPrivateKey'> & {
53
- balanceAtomic?: string
54
- balanceLamports?: number
55
- balanceFormatted?: string
56
- balanceSymbol?: string
57
- isActive?: boolean
58
- }
59
-
60
51
  function SectionCard({
61
52
  title,
62
53
  description,
@@ -266,7 +257,6 @@ export function AgentSheet() {
266
257
  const [dailyBudget, setDailyBudget] = useState('')
267
258
  const [monthlyBudget, setMonthlyBudget] = useState('')
268
259
  const [budgetAction, setBudgetAction] = useState<'warn' | 'block'>('warn')
269
- const [agentWallets, setAgentWallets] = useState<SafeAgentWallet[]>([])
270
260
  const [addingKey, setAddingKey] = useState(false)
271
261
  const [newKeyName, setNewKeyName] = useState('')
272
262
  const [newKeyValue, setNewKeyValue] = useState('')
@@ -297,21 +287,6 @@ export function AgentSheet() {
297
287
  e.target.value = ''
298
288
  }
299
289
 
300
- const loadAgentWallets = useCallback(async (agentId: string) => {
301
- try {
302
- const wallets = await api<Record<string, SafeAgentWallet>>('GET', `/wallets?agentId=${encodeURIComponent(agentId)}`)
303
- const matches = Object.values(wallets)
304
- .filter((wallet) => wallet.agentId === agentId)
305
- .sort((a, b) => {
306
- if ((a.isActive ? 1 : 0) !== (b.isActive ? 1 : 0)) return a.isActive ? -1 : 1
307
- return a.chain.localeCompare(b.chain)
308
- })
309
- setAgentWallets(matches)
310
- } catch {
311
- setAgentWallets([])
312
- }
313
- }, [])
314
-
315
290
  const agentSelectableProviders = useMemo(
316
291
  () => buildAgentSelectableProviders(providers, providerConfigs),
317
292
  [providers, providerConfigs],
@@ -487,7 +462,6 @@ export function AgentSheet() {
487
462
  setDailyBudget(typeof editing.dailyBudget === 'number' && editing.dailyBudget > 0 ? String(editing.dailyBudget) : '')
488
463
  setMonthlyBudget(typeof editing.monthlyBudget === 'number' && editing.monthlyBudget > 0 ? String(editing.monthlyBudget) : '')
489
464
  setBudgetAction(editing.budgetAction || 'warn')
490
- void loadAgentWallets(editing.id)
491
465
  } else if (useAppStore.getState().agentPrefill) {
492
466
  // Duplicate mode — prefill from source agent, then clear
493
467
  const src = useAppStore.getState().agentPrefill!
@@ -567,7 +541,6 @@ export function AgentSheet() {
567
541
  setDailyBudget(typeof src.dailyBudget === 'number' && src.dailyBudget > 0 ? String(src.dailyBudget) : '')
568
542
  setMonthlyBudget(typeof src.monthlyBudget === 'number' && src.monthlyBudget > 0 ? String(src.monthlyBudget) : '')
569
543
  setBudgetAction(src.budgetAction || 'warn')
570
- setAgentWallets([])
571
544
  } else {
572
545
  setName('')
573
546
  setDescription('')
@@ -634,7 +607,6 @@ export function AgentSheet() {
634
607
  setDailyBudget('')
635
608
  setMonthlyBudget('')
636
609
  setBudgetAction('warn')
637
- setAgentWallets([])
638
610
  }
639
611
  }
640
612
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -2657,7 +2629,7 @@ export function AgentSheet() {
2657
2629
 
2658
2630
  <SectionCard
2659
2631
  title="Utilities"
2660
- description="Import and export agents, and manage any attached wallets."
2632
+ description="Import and export agents."
2661
2633
  className="mb-0 border-white/[0.05] bg-white/[0.01]"
2662
2634
  >
2663
2635
  <div className="flex flex-wrap gap-3">
@@ -2681,16 +2653,6 @@ export function AgentSheet() {
2681
2653
  </button>
2682
2654
  )}
2683
2655
  </div>
2684
- {editing && (
2685
- <div className="mt-6">
2686
- <WalletSection
2687
- agentId={editing.id}
2688
- wallets={agentWallets}
2689
- activeWalletId={editing.activeWalletId || null}
2690
- onWalletCreated={() => loadAgentWallets(editing.id)}
2691
- />
2692
- </div>
2693
- )}
2694
2656
  </SectionCard>
2695
2657
  </AdvancedSettingsSection>
2696
2658
  )}
@@ -6,7 +6,6 @@ import type { Agent, MemoryEntry, Session } from '@/types'
6
6
  import { useAppStore } from '@/stores/use-app-store'
7
7
  import { useChatStore } from '@/stores/use-chat-store'
8
8
  import { api } from '@/lib/app/api-client'
9
- import { dedup } from '@/lib/shared-utils'
10
9
  import { AgentAvatar } from './agent-avatar'
11
10
  import { AgentFilesEditor } from './agent-files-editor'
12
11
  import { OpenClawSkillsPanel } from './openclaw-skills-panel'
@@ -205,25 +204,6 @@ function ToggleSwitch({ on, onChange, disabled }: { on: boolean; onChange: () =>
205
204
  )
206
205
  }
207
206
 
208
- // --- Wallet helpers (extracted from chat-header) ---
209
-
210
- function getAgentWalletIds(agent: { walletIds?: string[]; walletId?: string | null } | null | undefined): string[] {
211
- const ids = Array.isArray(agent?.walletIds)
212
- ? agent.walletIds.filter((value): value is string => typeof value === 'string' && value.trim().length > 0)
213
- : []
214
- const legacy = typeof agent?.walletId === 'string' && agent.walletId.trim()
215
- ? [agent.walletId.trim()]
216
- : []
217
- return dedup([...ids, ...legacy])
218
- }
219
-
220
- function getAgentActiveWalletId(agent: { activeWalletId?: string | null; walletIds?: string[]; walletId?: string | null } | null | undefined): string | null {
221
- const walletIds = getAgentWalletIds(agent)
222
- if (typeof agent?.activeWalletId === 'string' && walletIds.includes(agent.activeWalletId)) return agent.activeWalletId
223
- if (typeof agent?.walletId === 'string' && walletIds.includes(agent.walletId)) return agent.walletId
224
- return walletIds[0] || null
225
- }
226
-
227
207
  // --- Main component ---
228
208
 
229
209
  export function InspectorPanel({ agent, session, onEditAgent, onDuplicateAgent, onClearHistory, onDeleteAgent, onDeleteChat, isMainChat }: Props) {
@@ -345,7 +325,6 @@ function DashboardTab({ agent, session }: { agent: Agent; session: Session }) {
345
325
  <IdentityCard agent={agent} />
346
326
  {agent.provider === 'openclaw' && <OpenClawActionsSection agent={agent} />}
347
327
  <HeartbeatSection agent={agent} session={session} />
348
- <WalletSection agent={agent} />
349
328
  <ToolsSection agent={agent} session={session} />
350
329
  <AudioSection />
351
330
  <MemorySection agentId={agent.id} />
@@ -613,68 +592,6 @@ function HeartbeatSection({ agent, session }: { agent: Agent; session: Session }
613
592
  )
614
593
  }
615
594
 
616
- // ─── Wallet Section ──────────────────────────────────────────────
617
-
618
- function WalletSection({ agent }: { agent: Agent }) {
619
- const setWalletPanelAgentId = useAppStore((s) => s.setWalletPanelAgentId)
620
- const navigateTo = useNavigate()
621
- const agentWalletIds = useMemo(() => getAgentWalletIds(agent), [agent])
622
- const activeWalletId = useMemo(() => getAgentActiveWalletId(agent), [agent])
623
- const [walletBalance, setWalletBalance] = useState<{ formatted: string; symbol: string; assets?: number } | null>(null)
624
-
625
- useEffect(() => {
626
- if (!activeWalletId) return
627
- let cancelled = false
628
- api<{ balanceFormatted?: string; balanceSymbol?: string; portfolioSummary?: { nonZeroAssets?: number } }>('GET', `/wallets/${activeWalletId}?cached=1`)
629
- .then((data) => {
630
- if (cancelled) return
631
- if (data.balanceFormatted && data.balanceSymbol) {
632
- setWalletBalance({
633
- formatted: data.balanceFormatted,
634
- symbol: data.balanceSymbol,
635
- assets: typeof data.portfolioSummary?.nonZeroAssets === 'number' ? data.portfolioSummary.nonZeroAssets : undefined,
636
- })
637
- }
638
- })
639
- .catch(() => {})
640
- return () => { cancelled = true }
641
- }, [activeWalletId])
642
-
643
- if (agentWalletIds.length === 0) return null
644
-
645
- const handleClick = () => {
646
- setWalletPanelAgentId(agent.id)
647
- navigateTo('wallets')
648
- }
649
-
650
- return (
651
- <div className={panelCardClass('p-4')}>
652
- <SectionLabel>Wallet</SectionLabel>
653
- <button
654
- type="button"
655
- onClick={handleClick}
656
- className="flex items-center gap-2 w-full bg-transparent border-none cursor-pointer text-left group"
657
- >
658
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-text-3/50 shrink-0">
659
- <rect x="2" y="6" width="20" height="14" rx="2" />
660
- <path d="M22 10H18a2 2 0 0 0 0 4h4" />
661
- </svg>
662
- {walletBalance ? (
663
- <span className="text-[13px] text-text-2 font-600 group-hover:text-accent-bright transition-colors">
664
- {walletBalance.formatted} {walletBalance.symbol}
665
- {walletBalance.assets && walletBalance.assets > 1 ? ` +${walletBalance.assets - 1} assets` : ''}
666
- </span>
667
- ) : (
668
- <span className="text-[13px] text-text-3/50 group-hover:text-text-3 transition-colors">View wallet</span>
669
- )}
670
- <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="ml-auto text-text-3/30 group-hover:text-text-3/60 transition-colors shrink-0">
671
- <polyline points="9 18 15 12 9 6" />
672
- </svg>
673
- </button>
674
- </div>
675
- )
676
- }
677
-
678
595
  // ─── Tools Section ───────────────────────────────────────────────
679
596
 
680
597
  function ToolsSection({ agent, session }: { agent: Agent; session: Session }) {