@swarmclawai/swarmclaw 0.6.4 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +62 -30
  2. package/package.json +10 -1
  3. package/src/app/api/agents/[id]/clone/route.ts +40 -0
  4. package/src/app/api/agents/route.ts +39 -14
  5. package/src/app/api/chatrooms/[id]/chat/route.ts +58 -3
  6. package/src/app/api/chatrooms/[id]/moderate/route.ts +150 -0
  7. package/src/app/api/chatrooms/[id]/route.ts +34 -2
  8. package/src/app/api/chatrooms/route.ts +26 -3
  9. package/src/app/api/connectors/[id]/health/route.ts +64 -0
  10. package/src/app/api/connectors/route.ts +17 -2
  11. package/src/app/api/knowledge/route.ts +6 -1
  12. package/src/app/api/openclaw/doctor/route.ts +17 -0
  13. package/src/app/api/schedules/[id]/run/route.ts +3 -0
  14. package/src/app/api/sessions/[id]/chat/route.ts +5 -1
  15. package/src/app/api/sessions/route.ts +11 -2
  16. package/src/app/api/tasks/[id]/route.ts +18 -13
  17. package/src/app/api/tasks/route.ts +44 -1
  18. package/src/app/api/usage/route.ts +16 -7
  19. package/src/app/api/wallets/[id]/approve/route.ts +62 -0
  20. package/src/app/api/wallets/[id]/balance-history/route.ts +18 -0
  21. package/src/app/api/wallets/[id]/route.ts +118 -0
  22. package/src/app/api/wallets/[id]/send/route.ts +118 -0
  23. package/src/app/api/wallets/[id]/transactions/route.ts +18 -0
  24. package/src/app/api/wallets/route.ts +74 -0
  25. package/src/app/globals.css +8 -0
  26. package/src/cli/index.js +20 -0
  27. package/src/cli/index.ts +223 -39
  28. package/src/cli/spec.js +14 -0
  29. package/src/components/agents/agent-avatar.tsx +15 -1
  30. package/src/components/agents/agent-card.tsx +38 -6
  31. package/src/components/agents/agent-chat-list.tsx +79 -3
  32. package/src/components/agents/agent-sheet.tsx +191 -26
  33. package/src/components/auth/setup-wizard.tsx +268 -353
  34. package/src/components/chat/chat-area.tsx +24 -9
  35. package/src/components/chat/chat-header.tsx +48 -19
  36. package/src/components/chat/chat-tool-toggles.tsx +1 -1
  37. package/src/components/chat/delegation-banner.test.ts +27 -0
  38. package/src/components/chat/delegation-banner.tsx +109 -23
  39. package/src/components/chat/message-bubble.tsx +17 -16
  40. package/src/components/chat/message-list.tsx +6 -5
  41. package/src/components/chat/streaming-bubble.tsx +3 -2
  42. package/src/components/chat/thinking-indicator.tsx +3 -2
  43. package/src/components/chat/transfer-agent-picker.tsx +1 -1
  44. package/src/components/chatrooms/agent-hover-card.tsx +1 -1
  45. package/src/components/chatrooms/chatroom-input.tsx +1 -1
  46. package/src/components/chatrooms/chatroom-message.tsx +165 -23
  47. package/src/components/chatrooms/chatroom-sheet.tsx +289 -4
  48. package/src/components/chatrooms/chatroom-typing-bar.tsx +1 -1
  49. package/src/components/chatrooms/chatroom-view.tsx +62 -17
  50. package/src/components/connectors/connector-health.tsx +120 -0
  51. package/src/components/connectors/connector-list.tsx +1 -1
  52. package/src/components/connectors/connector-sheet.tsx +9 -0
  53. package/src/components/home/home-view.tsx +25 -3
  54. package/src/components/input/chat-input.tsx +8 -1
  55. package/src/components/knowledge/knowledge-list.tsx +1 -1
  56. package/src/components/knowledge/knowledge-sheet.tsx +1 -1
  57. package/src/components/layout/app-layout.tsx +35 -4
  58. package/src/components/memory/memory-agent-list.tsx +1 -1
  59. package/src/components/memory/memory-browser.tsx +1 -0
  60. package/src/components/memory/memory-card.tsx +3 -2
  61. package/src/components/memory/memory-detail.tsx +3 -3
  62. package/src/components/memory/memory-sheet.tsx +2 -2
  63. package/src/components/projects/project-detail.tsx +4 -4
  64. package/src/components/schedules/schedule-list.tsx +55 -9
  65. package/src/components/schedules/schedule-sheet.tsx +134 -23
  66. package/src/components/secrets/secret-sheet.tsx +1 -1
  67. package/src/components/secrets/secrets-list.tsx +1 -1
  68. package/src/components/sessions/session-card.tsx +1 -1
  69. package/src/components/shared/agent-picker-list.tsx +1 -1
  70. package/src/components/shared/agent-switch-dialog.tsx +1 -1
  71. package/src/components/shared/command-palette.tsx +237 -0
  72. package/src/components/shared/connector-platform-icon.tsx +1 -0
  73. package/src/components/shared/settings/section-user-preferences.tsx +4 -4
  74. package/src/components/skills/skill-list.tsx +1 -1
  75. package/src/components/skills/skill-sheet.tsx +1 -1
  76. package/src/components/tasks/task-board.tsx +3 -3
  77. package/src/components/tasks/task-card.tsx +22 -2
  78. package/src/components/tasks/task-sheet.tsx +112 -17
  79. package/src/components/usage/metrics-dashboard.tsx +13 -25
  80. package/src/components/wallets/wallet-approval-dialog.tsx +99 -0
  81. package/src/components/wallets/wallet-panel.tsx +616 -0
  82. package/src/components/wallets/wallet-section.tsx +100 -0
  83. package/src/hooks/use-swipe.ts +49 -0
  84. package/src/lib/providers/anthropic.ts +16 -2
  85. package/src/lib/providers/claude-cli.ts +7 -1
  86. package/src/lib/providers/index.ts +7 -0
  87. package/src/lib/providers/ollama.ts +16 -2
  88. package/src/lib/providers/openai.ts +7 -2
  89. package/src/lib/providers/openclaw.ts +6 -1
  90. package/src/lib/providers/provider-defaults.ts +7 -0
  91. package/src/lib/schedule-templates.ts +115 -0
  92. package/src/lib/server/agent-registry.ts +2 -2
  93. package/src/lib/server/alert-dispatch.ts +64 -0
  94. package/src/lib/server/chat-execution.ts +76 -4
  95. package/src/lib/server/chatroom-health.ts +60 -0
  96. package/src/lib/server/chatroom-helpers.test.ts +94 -0
  97. package/src/lib/server/chatroom-helpers.ts +86 -12
  98. package/src/lib/server/chatroom-routing.ts +65 -0
  99. package/src/lib/server/connectors/discord.ts +3 -0
  100. package/src/lib/server/connectors/email.ts +267 -0
  101. package/src/lib/server/connectors/inbound-audio-transcription.test.ts +191 -0
  102. package/src/lib/server/connectors/inbound-audio-transcription.ts +261 -0
  103. package/src/lib/server/connectors/manager.ts +239 -5
  104. package/src/lib/server/connectors/openclaw.ts +3 -0
  105. package/src/lib/server/connectors/slack.ts +6 -0
  106. package/src/lib/server/connectors/telegram.ts +18 -0
  107. package/src/lib/server/connectors/types.ts +2 -0
  108. package/src/lib/server/connectors/whatsapp-text.test.ts +29 -0
  109. package/src/lib/server/connectors/whatsapp-text.ts +26 -0
  110. package/src/lib/server/connectors/whatsapp.ts +17 -5
  111. package/src/lib/server/cost.ts +70 -0
  112. package/src/lib/server/create-notification.ts +2 -0
  113. package/src/lib/server/daemon-state.ts +124 -0
  114. package/src/lib/server/dag-validation.ts +115 -0
  115. package/src/lib/server/memory-db.ts +12 -7
  116. package/src/lib/server/openclaw-doctor.ts +48 -0
  117. package/src/lib/server/orchestrator-lg.ts +12 -2
  118. package/src/lib/server/orchestrator.ts +6 -1
  119. package/src/lib/server/queue-followups.test.ts +224 -0
  120. package/src/lib/server/queue.ts +238 -24
  121. package/src/lib/server/scheduler.ts +3 -0
  122. package/src/lib/server/session-run-manager.ts +22 -1
  123. package/src/lib/server/session-tools/chatroom.ts +11 -2
  124. package/src/lib/server/session-tools/context-mgmt.ts +2 -2
  125. package/src/lib/server/session-tools/index.ts +8 -2
  126. package/src/lib/server/session-tools/memory.ts +23 -4
  127. package/src/lib/server/session-tools/openclaw-workspace.ts +132 -0
  128. package/src/lib/server/session-tools/shell.ts +1 -1
  129. package/src/lib/server/session-tools/wallet.ts +124 -0
  130. package/src/lib/server/session-tools/web.ts +2 -2
  131. package/src/lib/server/solana.ts +122 -0
  132. package/src/lib/server/storage.ts +158 -6
  133. package/src/lib/server/stream-agent-chat.ts +126 -63
  134. package/src/lib/server/task-mention.test.ts +41 -0
  135. package/src/lib/server/task-mention.ts +3 -2
  136. package/src/lib/setup-defaults.ts +277 -0
  137. package/src/lib/tool-definitions.ts +1 -0
  138. package/src/lib/validation/schemas.ts +69 -0
  139. package/src/lib/view-routes.ts +1 -0
  140. package/src/stores/use-app-store.ts +15 -3
  141. package/src/stores/use-chatroom-store.ts +52 -2
  142. package/src/types/index.ts +98 -2
  143. package/tsconfig.json +2 -1
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Shared setup defaults used by both the web wizard and CLI.
3
+ * Isomorphic — no 'use client', no server imports.
4
+ */
5
+
6
+ export type SetupProvider =
7
+ | 'anthropic'
8
+ | 'openai'
9
+ | 'google'
10
+ | 'deepseek'
11
+ | 'groq'
12
+ | 'together'
13
+ | 'mistral'
14
+ | 'xai'
15
+ | 'fireworks'
16
+ | 'ollama'
17
+ | 'openclaw'
18
+
19
+ export interface SetupProviderOption {
20
+ id: SetupProvider
21
+ name: string
22
+ description: string
23
+ requiresKey: boolean
24
+ supportsEndpoint: boolean
25
+ defaultEndpoint?: string
26
+ keyUrl?: string
27
+ keyLabel?: string
28
+ keyPlaceholder?: string
29
+ optionalKey?: boolean
30
+ badge?: string
31
+ icon: string
32
+ }
33
+
34
+ export const SETUP_PROVIDERS: SetupProviderOption[] = [
35
+ {
36
+ id: 'openai',
37
+ name: 'OpenAI',
38
+ description: 'Great default for most users. Fast, reliable GPT models.',
39
+ requiresKey: true,
40
+ supportsEndpoint: true,
41
+ defaultEndpoint: 'https://api.openai.com/v1',
42
+ keyUrl: 'https://platform.openai.com/api-keys',
43
+ keyLabel: 'platform.openai.com',
44
+ badge: 'Recommended',
45
+ icon: 'O',
46
+ },
47
+ {
48
+ id: 'anthropic',
49
+ name: 'Anthropic',
50
+ description: 'Claude models — strong for coding, analysis, and long-form reasoning.',
51
+ requiresKey: true,
52
+ supportsEndpoint: false,
53
+ keyUrl: 'https://console.anthropic.com/settings/keys',
54
+ keyLabel: 'console.anthropic.com',
55
+ icon: 'A',
56
+ },
57
+ {
58
+ id: 'google',
59
+ name: 'Google Gemini',
60
+ description: 'Gemini models with strong multimodal and coding support.',
61
+ requiresKey: true,
62
+ supportsEndpoint: false,
63
+ keyUrl: 'https://aistudio.google.com/app/apikey',
64
+ keyLabel: 'aistudio.google.com',
65
+ keyPlaceholder: 'AIza...',
66
+ icon: 'G',
67
+ },
68
+ {
69
+ id: 'deepseek',
70
+ name: 'DeepSeek',
71
+ description: 'High-value reasoning and coding models from DeepSeek.',
72
+ requiresKey: true,
73
+ supportsEndpoint: false,
74
+ keyUrl: 'https://platform.deepseek.com/api_keys',
75
+ keyLabel: 'platform.deepseek.com',
76
+ icon: 'D',
77
+ },
78
+ {
79
+ id: 'groq',
80
+ name: 'Groq',
81
+ description: 'Very fast inference with open and reasoning model options.',
82
+ requiresKey: true,
83
+ supportsEndpoint: false,
84
+ keyUrl: 'https://console.groq.com/keys',
85
+ keyLabel: 'console.groq.com',
86
+ icon: 'G',
87
+ },
88
+ {
89
+ id: 'together',
90
+ name: 'Together AI',
91
+ description: 'Broad catalog of open models with OpenAI-compatible APIs.',
92
+ requiresKey: true,
93
+ supportsEndpoint: false,
94
+ keyUrl: 'https://api.together.xyz/settings/api-keys',
95
+ keyLabel: 'api.together.xyz',
96
+ icon: 'T',
97
+ },
98
+ {
99
+ id: 'mistral',
100
+ name: 'Mistral AI',
101
+ description: 'Efficient frontier models with strong latency and quality.',
102
+ requiresKey: true,
103
+ supportsEndpoint: false,
104
+ keyUrl: 'https://console.mistral.ai/api-keys/',
105
+ keyLabel: 'console.mistral.ai',
106
+ icon: 'M',
107
+ },
108
+ {
109
+ id: 'xai',
110
+ name: 'xAI (Grok)',
111
+ description: 'Grok models for fast answers, coding, and analysis.',
112
+ requiresKey: true,
113
+ supportsEndpoint: false,
114
+ keyUrl: 'https://console.x.ai',
115
+ keyLabel: 'console.x.ai',
116
+ icon: 'X',
117
+ },
118
+ {
119
+ id: 'fireworks',
120
+ name: 'Fireworks AI',
121
+ description: 'Serverless and optimized open-model inference endpoints.',
122
+ requiresKey: true,
123
+ supportsEndpoint: false,
124
+ keyUrl: 'https://fireworks.ai/account/api-keys',
125
+ keyLabel: 'fireworks.ai',
126
+ icon: 'F',
127
+ },
128
+ {
129
+ id: 'openclaw',
130
+ name: 'OpenClaw',
131
+ description: 'Connect to your local or remote OpenClaw gateway (multi-OpenClaw ready).',
132
+ requiresKey: false,
133
+ supportsEndpoint: true,
134
+ defaultEndpoint: 'http://localhost:18789/v1',
135
+ optionalKey: true,
136
+ badge: 'OpenClaw',
137
+ icon: 'C',
138
+ },
139
+ {
140
+ id: 'ollama',
141
+ name: 'Ollama',
142
+ description: 'Run local open-source models. No API key required.',
143
+ requiresKey: false,
144
+ supportsEndpoint: true,
145
+ defaultEndpoint: 'http://localhost:11434',
146
+ badge: 'Local',
147
+ icon: 'L',
148
+ },
149
+ ]
150
+
151
+ export const STARTER_AGENT_TOOLS = [
152
+ 'memory',
153
+ 'files',
154
+ 'web_search',
155
+ 'web_fetch',
156
+ 'browser',
157
+ 'manage_agents',
158
+ 'manage_tasks',
159
+ 'manage_schedules',
160
+ 'manage_skills',
161
+ 'manage_connectors',
162
+ 'manage_sessions',
163
+ 'manage_secrets',
164
+ 'manage_documents',
165
+ 'manage_webhooks',
166
+ 'claude_code',
167
+ 'codex_cli',
168
+ 'opencode_cli',
169
+ 'openclaw_workspace',
170
+ ]
171
+
172
+ export const SWARMCLAW_ASSISTANT_PROMPT = `You are the default SwarmClaw assistant inside the SwarmClaw dashboard.
173
+
174
+ Primary objective:
175
+ - Help the user operate SwarmClaw itself before anything else.
176
+
177
+ When the user asks about SwarmClaw, prioritize concrete guidance with exact UI paths and commands:
178
+ - Sessions: create, configure provider/model, and run chats.
179
+ - Agents: create specialist agents/orchestrators, set provider/model, tools, and prompts.
180
+ - Providers: connect API keys/endpoints, troubleshoot auth/model issues.
181
+ - Tasks + Schedules: queue work and automate recurring runs.
182
+ - Skills + Connectors + Webhooks + Secrets + Memory: explain when to use each and how to configure safely.
183
+
184
+ Behavior:
185
+ - Be concise, direct, and action-oriented.
186
+ - If the request is ambiguous, ask one focused clarifying question.
187
+ - Prefer step-by-step instructions that can be executed immediately.
188
+ - When the user asks for direct execution (for example browsing, screenshots, research, or file edits), use available tools and return real results instead of only describing what to do.
189
+ - If a capability depends on provider/tool configuration, call that out explicitly.`
190
+
191
+ export interface DefaultAgentConfig {
192
+ name: string
193
+ description: string
194
+ systemPrompt: string
195
+ model: string
196
+ tools: string[]
197
+ }
198
+
199
+ export const DEFAULT_AGENTS: Record<SetupProvider, DefaultAgentConfig> = {
200
+ anthropic: {
201
+ name: 'Claude',
202
+ description: 'A helpful Claude-powered assistant.',
203
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
204
+ model: 'claude-sonnet-4-6',
205
+ tools: STARTER_AGENT_TOOLS,
206
+ },
207
+ openai: {
208
+ name: 'Atlas',
209
+ description: 'A helpful GPT-powered assistant.',
210
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
211
+ model: 'gpt-4o',
212
+ tools: STARTER_AGENT_TOOLS,
213
+ },
214
+ google: {
215
+ name: 'Gemini',
216
+ description: 'A helpful Gemini-powered assistant.',
217
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
218
+ model: 'gemini-2.5-pro',
219
+ tools: STARTER_AGENT_TOOLS,
220
+ },
221
+ deepseek: {
222
+ name: 'DeepSeek',
223
+ description: 'A helpful DeepSeek-powered assistant.',
224
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
225
+ model: 'deepseek-chat',
226
+ tools: STARTER_AGENT_TOOLS,
227
+ },
228
+ groq: {
229
+ name: 'Bolt',
230
+ description: 'A low-latency assistant powered by Groq.',
231
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
232
+ model: 'llama-3.3-70b-versatile',
233
+ tools: STARTER_AGENT_TOOLS,
234
+ },
235
+ together: {
236
+ name: 'Mosaic',
237
+ description: 'A helpful assistant powered by Together AI.',
238
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
239
+ model: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8',
240
+ tools: STARTER_AGENT_TOOLS,
241
+ },
242
+ mistral: {
243
+ name: 'Mistral',
244
+ description: 'A helpful assistant powered by Mistral.',
245
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
246
+ model: 'mistral-large-latest',
247
+ tools: STARTER_AGENT_TOOLS,
248
+ },
249
+ xai: {
250
+ name: 'Grok',
251
+ description: 'A helpful assistant powered by xAI Grok.',
252
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
253
+ model: 'grok-3',
254
+ tools: STARTER_AGENT_TOOLS,
255
+ },
256
+ fireworks: {
257
+ name: 'Spark',
258
+ description: 'A helpful assistant powered by Fireworks AI.',
259
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
260
+ model: 'accounts/fireworks/models/deepseek-r1-0528',
261
+ tools: STARTER_AGENT_TOOLS,
262
+ },
263
+ ollama: {
264
+ name: 'Local',
265
+ description: 'A local assistant running through Ollama.',
266
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
267
+ model: 'llama3',
268
+ tools: STARTER_AGENT_TOOLS,
269
+ },
270
+ openclaw: {
271
+ name: 'OpenClaw Operator',
272
+ description: 'A manager agent for talking to and coordinating OpenClaw instances.',
273
+ systemPrompt: 'You are an operator focused on reliable execution, clear status updates, and task completion.',
274
+ model: 'default',
275
+ tools: STARTER_AGENT_TOOLS,
276
+ },
277
+ }
@@ -24,6 +24,7 @@ export const AVAILABLE_TOOLS: ToolDefinition[] = [
24
24
  { id: 'create_spreadsheet', label: 'Create Spreadsheet', description: 'Create Excel or CSV files from structured data' },
25
25
  { id: 'http_request', label: 'HTTP Request', description: 'Make HTTP API calls (GET, POST, PUT, DELETE, etc.)' },
26
26
  { id: 'git', label: 'Git', description: 'Run structured git operations (status, commit, push, diff, etc.)' },
27
+ { id: 'wallet', label: 'Wallet', description: 'Manage agent crypto wallet — check balance, send SOL, view transactions' },
27
28
  ]
28
29
 
29
30
  export const PLATFORM_TOOLS: ToolDefinition[] = [
@@ -0,0 +1,69 @@
1
+ import { z } from 'zod'
2
+
3
+ export const AgentCreateSchema = z.object({
4
+ name: z.string().min(1, 'Agent name is required'),
5
+ provider: z.string().min(1, 'Provider is required'),
6
+ description: z.string().optional().default(''),
7
+ systemPrompt: z.string().optional().default(''),
8
+ model: z.string().optional().default(''),
9
+ credentialId: z.string().nullable().optional().default(null),
10
+ apiEndpoint: z.string().nullable().optional().default(null),
11
+ isOrchestrator: z.boolean().optional().default(false),
12
+ subAgentIds: z.array(z.string()).optional().default([]),
13
+ tools: z.array(z.string()).optional().default([]),
14
+ capabilities: z.array(z.string()).optional().default([]),
15
+ thinkingLevel: z.string().optional(),
16
+ soul: z.string().optional(),
17
+ })
18
+
19
+ export const ConnectorCreateSchema = z.object({
20
+ name: z.string().min(1, 'Connector name is required').optional(),
21
+ platform: z.enum([
22
+ 'discord', 'telegram', 'slack', 'whatsapp', 'openclaw',
23
+ 'bluebubbles', 'signal', 'teams', 'googlechat', 'matrix', 'email',
24
+ ]),
25
+ agentId: z.string().nullable().optional().default(null),
26
+ chatroomId: z.string().nullable().optional().default(null),
27
+ credentialId: z.string().nullable().optional().default(null),
28
+ config: z.record(z.string(), z.string()).optional().default({}),
29
+ autoStart: z.boolean().optional(),
30
+ })
31
+
32
+ export const TaskCreateSchema = z.object({
33
+ title: z.string().min(1, 'Task title is required'),
34
+ description: z.string().optional().default(''),
35
+ status: z.string().optional(),
36
+ agentId: z.string().optional().default(''),
37
+ projectId: z.string().nullable().optional(),
38
+ goalContract: z.string().nullable().optional(),
39
+ cwd: z.string().nullable().optional(),
40
+ file: z.string().nullable().optional(),
41
+ blockedBy: z.array(z.string()).optional(),
42
+ blocks: z.array(z.string()).optional(),
43
+ tags: z.array(z.string()).optional(),
44
+ maxAttempts: z.number().optional(),
45
+ retryBackoffSec: z.number().optional(),
46
+ priority: z.enum(['low', 'medium', 'high', 'critical']).optional(),
47
+ dueAt: z.number().nullable().optional(),
48
+ })
49
+
50
+ export const ChatroomCreateSchema = z.object({
51
+ name: z.string().min(1, 'Chatroom name is required'),
52
+ agentIds: z.array(z.string()).default([]),
53
+ description: z.string().optional().default(''),
54
+ chatMode: z.enum(['sequential', 'parallel']).optional(),
55
+ autoAddress: z.boolean().optional(),
56
+ routingRules: z.array(z.object({
57
+ id: z.string(),
58
+ type: z.enum(['keyword', 'capability']),
59
+ pattern: z.string().optional(),
60
+ keywords: z.array(z.string()).optional(),
61
+ agentId: z.string(),
62
+ priority: z.number(),
63
+ })).optional(),
64
+ })
65
+
66
+ /** Format ZodError into a 400-friendly payload */
67
+ export function formatZodError(err: z.ZodError) {
68
+ return { error: 'Validation failed', issues: err.issues.map((i) => ({ path: i.path.join('.'), message: i.message })) }
69
+ }
@@ -18,6 +18,7 @@ export const VIEW_TO_PATH: Record<AppView, string> = {
18
18
  knowledge: '/knowledge',
19
19
  plugins: '/plugins',
20
20
  usage: '/usage',
21
+ wallets: '/wallets',
21
22
  runs: '/runs',
22
23
  logs: '/logs',
23
24
  settings: '/settings',
@@ -68,6 +68,8 @@ interface AppState {
68
68
  setScheduleSheetOpen: (open: boolean) => void
69
69
  editingScheduleId: string | null
70
70
  setEditingScheduleId: (id: string | null) => void
71
+ scheduleTemplatePrefill: { name: string; taskPrompt: string; scheduleType: 'cron' | 'interval'; cron?: string; intervalMs?: number } | null
72
+ setScheduleTemplatePrefill: (prefill: { name: string; taskPrompt: string; scheduleType: 'cron' | 'interval'; cron?: string; intervalMs?: number } | null) => void
71
73
 
72
74
  memorySheetOpen: boolean
73
75
  setMemorySheetOpen: (open: boolean) => void
@@ -204,6 +206,10 @@ interface AppState {
204
206
  markAllNotificationsRead: () => Promise<void>
205
207
  clearReadNotifications: () => Promise<void>
206
208
 
209
+ // Wallets
210
+ walletPanelAgentId: string | null
211
+ setWalletPanelAgentId: (id: string | null) => void
212
+
207
213
  }
208
214
 
209
215
  export const useAppStore = create<AppState>((set, get) => ({
@@ -378,6 +384,8 @@ export const useAppStore = create<AppState>((set, get) => ({
378
384
  setScheduleSheetOpen: (open) => set({ scheduleSheetOpen: open }),
379
385
  editingScheduleId: null,
380
386
  setEditingScheduleId: (id) => set({ editingScheduleId: id }),
387
+ scheduleTemplatePrefill: null,
388
+ setScheduleTemplatePrefill: (prefill) => set({ scheduleTemplatePrefill: prefill }),
381
389
 
382
390
  memorySheetOpen: false,
383
391
  setMemorySheetOpen: (open) => set({ memorySheetOpen: open }),
@@ -604,9 +612,9 @@ export const useAppStore = create<AppState>((set, get) => ({
604
612
  inspectorTab: 'overview',
605
613
  setInspectorTab: (tab) => set({ inspectorTab: tab }),
606
614
 
607
- // Fleet sidebar filter
608
- fleetFilter: 'all',
609
- setFleetFilter: (filter) => set({ fleetFilter: filter }),
615
+ // Fleet sidebar filter (persisted to localStorage)
616
+ fleetFilter: (safeStorageGet('sc_fleet_filter') as FleetFilter) || 'all',
617
+ setFleetFilter: (filter) => { safeStorageSet('sc_fleet_filter', filter); set({ fleetFilter: filter }) },
610
618
 
611
619
  // Chat list filter
612
620
  chatFilter: 'all' as const,
@@ -684,4 +692,8 @@ export const useAppStore = create<AppState>((set, get) => ({
684
692
  }
685
693
  },
686
694
 
695
+ // Wallets
696
+ walletPanelAgentId: null,
697
+ setWalletPanelAgentId: (id) => set({ walletPanelAgentId: id }),
698
+
687
699
  }))
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { create } from 'zustand'
4
4
  import { api, getStoredAccessKey } from '@/lib/api-client'
5
- import type { Chatroom, ChatroomMessage, SSEEvent } from '@/types'
5
+ import type { Chatroom, ChatroomMessage, ChatroomRoutingRule, SSEEvent } from '@/types'
6
6
  import type { PendingFile } from '@/stores/use-chat-store'
7
7
 
8
8
  interface ToolEvent {
@@ -37,7 +37,7 @@ interface ChatroomState {
37
37
  setReplyingTo: (msg: ChatroomMessage | null) => void
38
38
 
39
39
  loadChatrooms: () => Promise<void>
40
- createChatroom: (data: { name: string; description?: string; agentIds?: string[]; chatMode?: 'sequential' | 'parallel'; autoAddress?: boolean }) => Promise<Chatroom>
40
+ createChatroom: (data: { name: string; description?: string; agentIds?: string[]; chatMode?: 'sequential' | 'parallel'; autoAddress?: boolean; routingRules?: ChatroomRoutingRule[] }) => Promise<Chatroom>
41
41
  updateChatroom: (id: string, data: Partial<Chatroom>) => Promise<void>
42
42
  deleteChatroom: (id: string) => Promise<void>
43
43
  setCurrentChatroom: (id: string | null) => void
@@ -48,6 +48,12 @@ interface ChatroomState {
48
48
  removeMember: (agentId: string) => Promise<void>
49
49
  setChatroomSheetOpen: (open: boolean) => void
50
50
  setEditingChatroomId: (id: string | null) => void
51
+
52
+ // Moderation
53
+ deleteMessage: (messageId: string, targetAgentId: string) => Promise<void>
54
+ muteAgent: (targetAgentId: string, minutes?: number) => Promise<void>
55
+ unmuteAgent: (targetAgentId: string) => Promise<void>
56
+ setMemberRole: (targetAgentId: string, role: 'admin' | 'moderator' | 'member') => Promise<void>
51
57
  }
52
58
 
53
59
  export const useChatroomStore = create<ChatroomState>((set, get) => ({
@@ -273,4 +279,48 @@ export const useChatroomStore = create<ChatroomState>((set, get) => ({
273
279
 
274
280
  setChatroomSheetOpen: (open) => set({ chatroomSheetOpen: open }),
275
281
  setEditingChatroomId: (id) => set({ editingChatroomId: id }),
282
+
283
+ // Moderation
284
+ deleteMessage: async (messageId, targetAgentId) => {
285
+ const { currentChatroomId } = get()
286
+ if (!currentChatroomId) return
287
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/moderate`, {
288
+ action: 'delete-message',
289
+ targetAgentId,
290
+ messageId,
291
+ })
292
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
293
+ },
294
+
295
+ muteAgent: async (targetAgentId, minutes = 30) => {
296
+ const { currentChatroomId } = get()
297
+ if (!currentChatroomId) return
298
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/moderate`, {
299
+ action: 'mute',
300
+ targetAgentId,
301
+ muteDurationMinutes: minutes,
302
+ })
303
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
304
+ },
305
+
306
+ unmuteAgent: async (targetAgentId) => {
307
+ const { currentChatroomId } = get()
308
+ if (!currentChatroomId) return
309
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/moderate`, {
310
+ action: 'unmute',
311
+ targetAgentId,
312
+ })
313
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
314
+ },
315
+
316
+ setMemberRole: async (targetAgentId, role) => {
317
+ const { currentChatroomId } = get()
318
+ if (!currentChatroomId) return
319
+ const chatroom = await api<Chatroom>('POST', `/chatrooms/${currentChatroomId}/moderate`, {
320
+ action: 'set-role',
321
+ targetAgentId,
322
+ role,
323
+ })
324
+ set((s) => ({ chatrooms: { ...s.chatrooms, [currentChatroomId]: chatroom } }))
325
+ },
276
326
  }))
@@ -264,16 +264,68 @@ export interface Agent {
264
264
  elevenLabsVoiceId?: string | null
265
265
  projectId?: string
266
266
  avatarSeed?: string
267
+ avatarUrl?: string | null
267
268
  pinned?: boolean
268
269
  lastUsedAt?: number
269
270
  totalCost?: number
270
271
  trashedAt?: number
271
272
  openclawSkillMode?: SkillAllowlistMode
272
273
  openclawAllowedSkills?: string[]
274
+ walletId?: string | null
275
+ monthlyBudget?: number | null
276
+ budgetAction?: 'warn' | 'block'
277
+ /** Runtime-enriched: current month's spend. Populated by GET /api/agents when monthlyBudget is set. */
278
+ monthlySpend?: number
273
279
  createdAt: number
274
280
  updatedAt: number
275
281
  }
276
282
 
283
+ // --- Agent Wallets ---
284
+
285
+ export type WalletChain = 'solana'
286
+
287
+ export interface AgentWallet {
288
+ id: string
289
+ agentId: string
290
+ chain: WalletChain
291
+ publicKey: string
292
+ encryptedPrivateKey: string // AES-256-GCM via encryptKey()
293
+ label?: string
294
+ spendingLimitLamports?: number // per-tx cap (default 0.1 SOL = 100_000_000)
295
+ dailyLimitLamports?: number // 24h rolling cap (default 1 SOL = 1_000_000_000)
296
+ requireApproval: boolean // default true
297
+ createdAt: number
298
+ updatedAt: number
299
+ }
300
+
301
+ export type WalletTransactionType = 'send' | 'receive' | 'swap'
302
+ export type WalletTransactionStatus = 'pending_approval' | 'pending' | 'confirmed' | 'failed' | 'denied'
303
+
304
+ export interface WalletTransaction {
305
+ id: string
306
+ walletId: string
307
+ agentId: string
308
+ chain: WalletChain
309
+ type: WalletTransactionType
310
+ signature: string
311
+ fromAddress: string
312
+ toAddress: string
313
+ amountLamports: number
314
+ feeLamports?: number
315
+ status: WalletTransactionStatus
316
+ memo?: string // agent's reason for tx
317
+ approvedBy?: 'user' | 'auto'
318
+ tokenMint?: string // null = native SOL
319
+ timestamp: number
320
+ }
321
+
322
+ export interface WalletBalanceSnapshot {
323
+ id: string
324
+ walletId: string
325
+ balanceLamports: number
326
+ timestamp: number
327
+ }
328
+
277
329
  export type AgentTool = 'browser'
278
330
 
279
331
  export interface ClaudeSkill {
@@ -356,10 +408,25 @@ export interface MemoryEntry {
356
408
  }
357
409
 
358
410
  export type SessionType = 'human' | 'orchestrated'
359
- export type AppView = 'home' | 'agents' | 'chatrooms' | 'schedules' | 'memory' | 'tasks' | 'secrets' | 'providers' | 'skills' | 'connectors' | 'webhooks' | 'mcp_servers' | 'knowledge' | 'plugins' | 'usage' | 'runs' | 'logs' | 'settings' | 'projects' | 'activity'
411
+ export type AppView = 'home' | 'agents' | 'chatrooms' | 'schedules' | 'memory' | 'tasks' | 'secrets' | 'providers' | 'skills' | 'connectors' | 'webhooks' | 'mcp_servers' | 'knowledge' | 'plugins' | 'usage' | 'wallets' | 'runs' | 'logs' | 'settings' | 'projects' | 'activity'
360
412
 
361
413
  // --- Chatrooms ---
362
414
 
415
+ export interface ChatroomRoutingRule {
416
+ id: string
417
+ type: 'keyword' | 'capability'
418
+ pattern?: string
419
+ keywords?: string[]
420
+ agentId: string
421
+ priority: number
422
+ }
423
+
424
+ export interface ChatroomMember {
425
+ agentId: string
426
+ role: 'admin' | 'moderator' | 'member'
427
+ mutedUntil?: string
428
+ }
429
+
363
430
  export interface ChatroomReaction {
364
431
  emoji: string
365
432
  reactorId: string // 'user' or agentId
@@ -387,10 +454,12 @@ export interface Chatroom {
387
454
  name: string
388
455
  description?: string
389
456
  agentIds: string[]
457
+ members?: ChatroomMember[]
390
458
  messages: ChatroomMessage[]
391
459
  pinnedMessageIds?: string[]
392
460
  chatMode?: 'sequential' | 'parallel'
393
461
  autoAddress?: boolean
462
+ routingRules?: ChatroomRoutingRule[]
394
463
  createdAt: number
395
464
  updatedAt: number
396
465
  }
@@ -578,6 +647,10 @@ export interface AppSettings {
578
647
  openclawWorkspacePath?: string | null
579
648
  openclawAutoSyncMemory?: boolean
580
649
  openclawAutoSyncSchedules?: boolean
650
+ // Outbound ops alert webhook
651
+ alertWebhookUrl?: string | null
652
+ alertWebhookType?: 'discord' | 'slack' | 'custom' | null
653
+ alertWebhookEvents?: ('error' | 'warning')[]
581
654
  }
582
655
 
583
656
  // --- Orchestrator Secrets ---
@@ -637,15 +710,29 @@ export interface Skill {
637
710
  updatedAt: number
638
711
  }
639
712
 
713
+ // --- Connector Health Events ---
714
+
715
+ export type ConnectorHealthEventType = 'started' | 'stopped' | 'error' | 'reconnected' | 'disconnected'
716
+
717
+ export interface ConnectorHealthEvent {
718
+ id: string
719
+ connectorId: string
720
+ event: ConnectorHealthEventType
721
+ message?: string
722
+ timestamp: string
723
+ }
724
+
640
725
  // --- Connectors (Chat Platform Bridges) ---
641
726
 
642
- export type ConnectorPlatform = 'discord' | 'telegram' | 'slack' | 'whatsapp' | 'openclaw' | 'bluebubbles' | 'signal' | 'teams' | 'googlechat' | 'matrix'
727
+ export type ConnectorPlatform = 'discord' | 'telegram' | 'slack' | 'whatsapp' | 'openclaw' | 'bluebubbles' | 'signal' | 'teams' | 'googlechat' | 'matrix' | 'email'
643
728
  export type ConnectorStatus = 'stopped' | 'running' | 'error'
644
729
 
645
730
  export interface MessageSource {
646
731
  platform: ConnectorPlatform
647
732
  connectorId: string
648
733
  connectorName: string
734
+ channelId?: string
735
+ senderId?: string
649
736
  senderName?: string
650
737
  }
651
738
 
@@ -711,8 +798,17 @@ export interface BoardTask {
711
798
  completionReportPath?: string | null
712
799
  result?: string | null
713
800
  error?: string | null
801
+ outputFiles?: string[]
802
+ artifacts?: Array<{
803
+ url: string
804
+ type: 'image' | 'video' | 'pdf' | 'file'
805
+ filename: string
806
+ }>
714
807
  comments?: TaskComment[]
715
808
  images?: string[]
809
+ createdByAgentId?: string | null
810
+ createdInSessionId?: string | null
811
+ delegatedByAgentId?: string | null
716
812
  createdAt: number
717
813
  updatedAt: number
718
814
  queuedAt?: number | null
package/tsconfig.json CHANGED
@@ -38,6 +38,7 @@
38
38
  ".next/dev/dev/types/**/*.ts"
39
39
  ],
40
40
  "exclude": [
41
- "node_modules"
41
+ "node_modules",
42
+ "src/cli"
42
43
  ]
43
44
  }