@swarmclawai/swarmclaw 0.6.6 → 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 (80) hide show
  1. package/README.md +57 -27
  2. package/package.json +6 -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 +17 -1
  6. package/src/app/api/chatrooms/[id]/moderate/route.ts +150 -0
  7. package/src/app/api/chatrooms/[id]/route.ts +19 -1
  8. package/src/app/api/chatrooms/route.ts +12 -2
  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/sessions/[id]/chat/route.ts +5 -1
  14. package/src/app/api/sessions/route.ts +11 -2
  15. package/src/app/api/tasks/[id]/route.ts +18 -13
  16. package/src/app/api/tasks/route.ts +20 -1
  17. package/src/app/api/usage/route.ts +16 -7
  18. package/src/cli/index.js +5 -0
  19. package/src/cli/index.ts +223 -39
  20. package/src/components/agents/agent-card.tsx +37 -6
  21. package/src/components/agents/agent-chat-list.tsx +78 -2
  22. package/src/components/agents/agent-sheet.tsx +79 -0
  23. package/src/components/auth/setup-wizard.tsx +268 -353
  24. package/src/components/chat/chat-area.tsx +22 -7
  25. package/src/components/chat/message-bubble.tsx +14 -14
  26. package/src/components/chat/message-list.tsx +1 -1
  27. package/src/components/chatrooms/chatroom-message.tsx +164 -22
  28. package/src/components/chatrooms/chatroom-sheet.tsx +288 -3
  29. package/src/components/chatrooms/chatroom-view.tsx +62 -17
  30. package/src/components/connectors/connector-health.tsx +120 -0
  31. package/src/components/connectors/connector-sheet.tsx +9 -0
  32. package/src/components/home/home-view.tsx +23 -2
  33. package/src/components/input/chat-input.tsx +8 -1
  34. package/src/components/layout/app-layout.tsx +17 -1
  35. package/src/components/schedules/schedule-list.tsx +55 -9
  36. package/src/components/schedules/schedule-sheet.tsx +134 -23
  37. package/src/components/shared/command-palette.tsx +237 -0
  38. package/src/components/shared/connector-platform-icon.tsx +1 -0
  39. package/src/components/tasks/task-card.tsx +22 -2
  40. package/src/components/tasks/task-sheet.tsx +91 -16
  41. package/src/components/usage/metrics-dashboard.tsx +13 -25
  42. package/src/hooks/use-swipe.ts +49 -0
  43. package/src/lib/providers/anthropic.ts +16 -2
  44. package/src/lib/providers/claude-cli.ts +7 -1
  45. package/src/lib/providers/index.ts +7 -0
  46. package/src/lib/providers/ollama.ts +16 -2
  47. package/src/lib/providers/openai.ts +7 -2
  48. package/src/lib/providers/openclaw.ts +6 -1
  49. package/src/lib/providers/provider-defaults.ts +7 -0
  50. package/src/lib/schedule-templates.ts +115 -0
  51. package/src/lib/server/alert-dispatch.ts +64 -0
  52. package/src/lib/server/chat-execution.ts +41 -1
  53. package/src/lib/server/chatroom-helpers.ts +22 -1
  54. package/src/lib/server/chatroom-routing.ts +65 -0
  55. package/src/lib/server/connectors/discord.ts +3 -0
  56. package/src/lib/server/connectors/email.ts +267 -0
  57. package/src/lib/server/connectors/manager.ts +159 -3
  58. package/src/lib/server/connectors/openclaw.ts +3 -0
  59. package/src/lib/server/connectors/slack.ts +6 -0
  60. package/src/lib/server/connectors/telegram.ts +18 -0
  61. package/src/lib/server/connectors/types.ts +2 -0
  62. package/src/lib/server/connectors/whatsapp.ts +9 -0
  63. package/src/lib/server/cost.ts +70 -0
  64. package/src/lib/server/create-notification.ts +2 -0
  65. package/src/lib/server/daemon-state.ts +124 -0
  66. package/src/lib/server/dag-validation.ts +115 -0
  67. package/src/lib/server/memory-db.ts +12 -7
  68. package/src/lib/server/openclaw-doctor.ts +48 -0
  69. package/src/lib/server/queue.ts +12 -0
  70. package/src/lib/server/session-run-manager.ts +22 -1
  71. package/src/lib/server/session-tools/index.ts +2 -0
  72. package/src/lib/server/session-tools/memory.ts +22 -3
  73. package/src/lib/server/session-tools/openclaw-workspace.ts +132 -0
  74. package/src/lib/server/storage.ts +120 -6
  75. package/src/lib/setup-defaults.ts +277 -0
  76. package/src/lib/validation/schemas.ts +69 -0
  77. package/src/stores/use-app-store.ts +7 -3
  78. package/src/stores/use-chatroom-store.ts +52 -2
  79. package/src/types/index.ts +38 -1
  80. 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
+ }
@@ -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
+ }
@@ -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
@@ -382,6 +384,8 @@ export const useAppStore = create<AppState>((set, get) => ({
382
384
  setScheduleSheetOpen: (open) => set({ scheduleSheetOpen: open }),
383
385
  editingScheduleId: null,
384
386
  setEditingScheduleId: (id) => set({ editingScheduleId: id }),
387
+ scheduleTemplatePrefill: null,
388
+ setScheduleTemplatePrefill: (prefill) => set({ scheduleTemplatePrefill: prefill }),
385
389
 
386
390
  memorySheetOpen: false,
387
391
  setMemorySheetOpen: (open) => set({ memorySheetOpen: open }),
@@ -608,9 +612,9 @@ export const useAppStore = create<AppState>((set, get) => ({
608
612
  inspectorTab: 'overview',
609
613
  setInspectorTab: (tab) => set({ inspectorTab: tab }),
610
614
 
611
- // Fleet sidebar filter
612
- fleetFilter: 'all',
613
- 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 }) },
614
618
 
615
619
  // Chat list filter
616
620
  chatFilter: 'all' as const,
@@ -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
  }))
@@ -272,6 +272,10 @@ export interface Agent {
272
272
  openclawSkillMode?: SkillAllowlistMode
273
273
  openclawAllowedSkills?: string[]
274
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
275
279
  createdAt: number
276
280
  updatedAt: number
277
281
  }
@@ -408,6 +412,21 @@ export type AppView = 'home' | 'agents' | 'chatrooms' | 'schedules' | 'memory' |
408
412
 
409
413
  // --- Chatrooms ---
410
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
+
411
430
  export interface ChatroomReaction {
412
431
  emoji: string
413
432
  reactorId: string // 'user' or agentId
@@ -435,10 +454,12 @@ export interface Chatroom {
435
454
  name: string
436
455
  description?: string
437
456
  agentIds: string[]
457
+ members?: ChatroomMember[]
438
458
  messages: ChatroomMessage[]
439
459
  pinnedMessageIds?: string[]
440
460
  chatMode?: 'sequential' | 'parallel'
441
461
  autoAddress?: boolean
462
+ routingRules?: ChatroomRoutingRule[]
442
463
  createdAt: number
443
464
  updatedAt: number
444
465
  }
@@ -626,6 +647,10 @@ export interface AppSettings {
626
647
  openclawWorkspacePath?: string | null
627
648
  openclawAutoSyncMemory?: boolean
628
649
  openclawAutoSyncSchedules?: boolean
650
+ // Outbound ops alert webhook
651
+ alertWebhookUrl?: string | null
652
+ alertWebhookType?: 'discord' | 'slack' | 'custom' | null
653
+ alertWebhookEvents?: ('error' | 'warning')[]
629
654
  }
630
655
 
631
656
  // --- Orchestrator Secrets ---
@@ -685,9 +710,21 @@ export interface Skill {
685
710
  updatedAt: number
686
711
  }
687
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
+
688
725
  // --- Connectors (Chat Platform Bridges) ---
689
726
 
690
- 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'
691
728
  export type ConnectorStatus = 'stopped' | 'running' | 'error'
692
729
 
693
730
  export interface MessageSource {
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
  }