@swarmclawai/swarmclaw 0.7.3 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +47 -40
  2. package/bin/package-manager.js +157 -0
  3. package/bin/package-manager.test.js +90 -0
  4. package/bin/server-cmd.js +38 -7
  5. package/bin/swarmclaw.js +54 -4
  6. package/bin/update-cmd.js +48 -10
  7. package/bin/update-cmd.test.js +55 -0
  8. package/package.json +8 -3
  9. package/scripts/postinstall.mjs +26 -0
  10. package/src/app/api/agents/[id]/route.ts +17 -0
  11. package/src/app/api/agents/[id]/thread/route.ts +3 -1
  12. package/src/app/api/agents/route.ts +23 -1
  13. package/src/app/api/auth/route.ts +1 -1
  14. package/src/app/api/chatrooms/[id]/chat/route.ts +16 -5
  15. package/src/app/api/chatrooms/[id]/pins/route.ts +2 -1
  16. package/src/app/api/chatrooms/[id]/reactions/route.ts +2 -1
  17. package/src/app/api/chatrooms/[id]/route.ts +6 -0
  18. package/src/app/api/chats/[id]/route.ts +12 -0
  19. package/src/app/api/chats/heartbeat/route.ts +2 -1
  20. package/src/app/api/chats/route.ts +7 -1
  21. package/src/app/api/external-agents/[id]/heartbeat/route.ts +33 -0
  22. package/src/app/api/external-agents/[id]/route.ts +31 -0
  23. package/src/app/api/external-agents/register/route.ts +3 -0
  24. package/src/app/api/external-agents/route.ts +66 -0
  25. package/src/app/api/gateways/[id]/health/route.ts +28 -0
  26. package/src/app/api/gateways/[id]/route.ts +79 -0
  27. package/src/app/api/gateways/route.ts +57 -0
  28. package/src/app/api/openclaw/gateway/route.ts +10 -7
  29. package/src/app/api/openclaw/skills/route.ts +1 -1
  30. package/src/app/api/providers/[id]/discover-models/route.ts +27 -0
  31. package/src/app/api/schedules/[id]/route.ts +38 -9
  32. package/src/app/api/schedules/route.ts +51 -28
  33. package/src/app/api/settings/route.ts +6 -10
  34. package/src/app/api/setup/doctor/route.ts +6 -4
  35. package/src/app/api/tasks/[id]/route.ts +2 -1
  36. package/src/app/api/tasks/bulk/route.ts +2 -2
  37. package/src/app/page.tsx +126 -15
  38. package/src/cli/binary.test.js +142 -0
  39. package/src/cli/index.js +34 -11
  40. package/src/cli/index.test.js +195 -0
  41. package/src/cli/index.ts +20 -4
  42. package/src/cli/server-cmd.test.js +59 -0
  43. package/src/cli/spec.js +20 -2
  44. package/src/components/agents/agent-sheet.tsx +249 -7
  45. package/src/components/agents/inspector-panel.tsx +3 -2
  46. package/src/components/agents/sandbox-env-panel.tsx +4 -1
  47. package/src/components/auth/setup-wizard.tsx +970 -275
  48. package/src/components/chat/chat-area.tsx +41 -14
  49. package/src/components/chat/chat-card.tsx +2 -1
  50. package/src/components/chat/chat-header.tsx +8 -13
  51. package/src/components/chat/chat-list.tsx +58 -20
  52. package/src/components/chat/message-list.tsx +142 -18
  53. package/src/components/chatrooms/chatroom-input.tsx +96 -33
  54. package/src/components/chatrooms/chatroom-list.tsx +141 -72
  55. package/src/components/chatrooms/chatroom-message.tsx +7 -6
  56. package/src/components/chatrooms/chatroom-sheet.tsx +13 -1
  57. package/src/components/chatrooms/chatroom-tool-request-banner.tsx +5 -2
  58. package/src/components/chatrooms/chatroom-view.tsx +157 -86
  59. package/src/components/chatrooms/reaction-picker.tsx +38 -33
  60. package/src/components/gateways/gateway-sheet.tsx +567 -0
  61. package/src/components/input/chat-input.tsx +135 -86
  62. package/src/components/layout/app-layout.tsx +2 -0
  63. package/src/components/memory/memory-browser.tsx +71 -6
  64. package/src/components/memory/memory-card.tsx +18 -0
  65. package/src/components/memory/memory-detail.tsx +58 -31
  66. package/src/components/memory/memory-sheet.tsx +32 -4
  67. package/src/components/projects/project-detail.tsx +7 -2
  68. package/src/components/providers/provider-list.tsx +158 -2
  69. package/src/components/providers/provider-sheet.tsx +81 -70
  70. package/src/components/shared/bottom-sheet.tsx +31 -15
  71. package/src/components/shared/confirm-dialog.tsx +45 -30
  72. package/src/components/shared/model-combobox.tsx +90 -8
  73. package/src/components/shared/settings/section-heartbeat.tsx +11 -6
  74. package/src/components/shared/settings/section-orchestrator.tsx +3 -0
  75. package/src/components/shared/settings/settings-page.tsx +5 -3
  76. package/src/components/tasks/approvals-panel.tsx +7 -1
  77. package/src/components/ui/dialog.tsx +2 -2
  78. package/src/components/wallets/wallet-approval-dialog.tsx +59 -54
  79. package/src/lib/heartbeat-defaults.ts +48 -0
  80. package/src/lib/memory-presentation.ts +59 -0
  81. package/src/lib/provider-model-discovery-client.ts +29 -0
  82. package/src/lib/providers/index.ts +12 -5
  83. package/src/lib/runtime-loop.ts +105 -3
  84. package/src/lib/safe-storage.ts +6 -1
  85. package/src/lib/server/agent-runtime-config.test.ts +141 -0
  86. package/src/lib/server/agent-runtime-config.ts +277 -0
  87. package/src/lib/server/approvals-auto-approve.test.ts +59 -0
  88. package/src/lib/server/build-llm.test.ts +13 -5
  89. package/src/lib/server/chat-execution-tool-events.test.ts +87 -2
  90. package/src/lib/server/chat-execution.ts +159 -71
  91. package/src/lib/server/chatroom-helpers.test.ts +7 -0
  92. package/src/lib/server/chatroom-helpers.ts +99 -6
  93. package/src/lib/server/chatroom-session-persistence.test.ts +87 -0
  94. package/src/lib/server/connectors/manager.ts +89 -61
  95. package/src/lib/server/connectors/slack.ts +1 -1
  96. package/src/lib/server/daemon-state.ts +3 -2
  97. package/src/lib/server/eval/agent-regression.test.ts +47 -0
  98. package/src/lib/server/eval/agent-regression.ts +1742 -0
  99. package/src/lib/server/eval/runner.ts +11 -1
  100. package/src/lib/server/eval/store.ts +2 -1
  101. package/src/lib/server/heartbeat-service.ts +10 -4
  102. package/src/lib/server/main-agent-loop.ts +13 -6
  103. package/src/lib/server/openclaw-exec-config.ts +4 -2
  104. package/src/lib/server/openclaw-gateway.ts +123 -36
  105. package/src/lib/server/orchestrator-lg.ts +1 -2
  106. package/src/lib/server/orchestrator.ts +3 -2
  107. package/src/lib/server/plugins.test.ts +9 -1
  108. package/src/lib/server/plugins.ts +12 -2
  109. package/src/lib/server/provider-model-discovery.ts +481 -0
  110. package/src/lib/server/queue.ts +1 -1
  111. package/src/lib/server/runtime-settings.test.ts +119 -0
  112. package/src/lib/server/runtime-settings.ts +12 -92
  113. package/src/lib/server/schedule-normalization.ts +187 -0
  114. package/src/lib/server/session-tools/autonomy-tools.test.ts +23 -0
  115. package/src/lib/server/session-tools/crud.ts +27 -3
  116. package/src/lib/server/session-tools/discovery-approvals.test.ts +170 -0
  117. package/src/lib/server/session-tools/discovery.ts +18 -8
  118. package/src/lib/server/session-tools/file-normalize.test.ts +5 -0
  119. package/src/lib/server/session-tools/file.ts +8 -2
  120. package/src/lib/server/session-tools/http.ts +9 -3
  121. package/src/lib/server/session-tools/index.ts +31 -1
  122. package/src/lib/server/session-tools/manage-schedules.test.ts +137 -0
  123. package/src/lib/server/session-tools/monitor.ts +14 -7
  124. package/src/lib/server/session-tools/openclaw-nodes.test.ts +111 -0
  125. package/src/lib/server/session-tools/openclaw-nodes.ts +86 -20
  126. package/src/lib/server/session-tools/platform.ts +1 -1
  127. package/src/lib/server/session-tools/plugin-creator.ts +9 -2
  128. package/src/lib/server/session-tools/sandbox.ts +51 -92
  129. package/src/lib/server/session-tools/session-info.ts +22 -1
  130. package/src/lib/server/session-tools/session-tools-wiring.test.ts +23 -0
  131. package/src/lib/server/session-tools/shell.ts +2 -2
  132. package/src/lib/server/session-tools/subagent.ts +3 -1
  133. package/src/lib/server/session-tools/web.ts +73 -30
  134. package/src/lib/server/storage.ts +29 -3
  135. package/src/lib/server/stream-agent-chat.test.ts +61 -0
  136. package/src/lib/server/stream-agent-chat.ts +139 -4
  137. package/src/lib/server/structured-extract.ts +1 -1
  138. package/src/lib/server/task-mention.ts +0 -1
  139. package/src/lib/server/tool-aliases.ts +37 -6
  140. package/src/lib/server/tool-capability-policy.ts +1 -1
  141. package/src/lib/setup-defaults.ts +352 -11
  142. package/src/lib/tool-definitions.ts +3 -4
  143. package/src/lib/validation/schemas.ts +55 -1
  144. package/src/stores/use-app-store.ts +43 -1
  145. package/src/stores/use-chatroom-store.ts +153 -26
  146. package/src/types/index.ts +189 -6
  147. package/src/app/api/chats/[id]/main-loop/route.ts +0 -13
@@ -22,6 +22,7 @@ export interface SetupProviderOption {
22
22
  description: string
23
23
  requiresKey: boolean
24
24
  supportsEndpoint: boolean
25
+ allowMultiple?: boolean
25
26
  defaultEndpoint?: string
26
27
  keyUrl?: string
27
28
  keyLabel?: string
@@ -44,6 +45,18 @@ export const SETUP_PROVIDERS: SetupProviderOption[] = [
44
45
  badge: 'Recommended',
45
46
  icon: 'O',
46
47
  },
48
+ {
49
+ id: 'openclaw',
50
+ name: 'OpenClaw',
51
+ description: 'Connect one or more local or remote OpenClaw gateways and map different starter agents to each one.',
52
+ requiresKey: false,
53
+ supportsEndpoint: true,
54
+ allowMultiple: true,
55
+ defaultEndpoint: 'http://localhost:18789/v1',
56
+ optionalKey: true,
57
+ badge: 'First-Tier',
58
+ icon: 'C',
59
+ },
47
60
  {
48
61
  id: 'anthropic',
49
62
  name: 'Anthropic',
@@ -125,17 +138,6 @@ export const SETUP_PROVIDERS: SetupProviderOption[] = [
125
138
  keyLabel: 'fireworks.ai',
126
139
  icon: 'F',
127
140
  },
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
141
  {
140
142
  id: 'ollama',
141
143
  name: 'Ollama',
@@ -189,6 +191,341 @@ Behavior:
189
191
  - 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.
190
192
  - If a capability depends on provider/tool configuration, call that out explicitly.`
191
193
 
194
+ const PERSONAL_ASSISTANT_PROMPT = `You are a personal AI copilot inside SwarmClaw.
195
+
196
+ Primary objective:
197
+ - Help the user make progress on whatever matters to them, whether that is research, planning, writing, building, organizing life admin, or running a business.
198
+
199
+ Behavior:
200
+ - Start from the user's intent, not from the tooling.
201
+ - Turn vague goals into concrete next steps.
202
+ - When useful, suggest tasks, schedules, or specialist agents, but do not force control-plane workflow on the user.
203
+ - Stay concise, practical, and execution-oriented.`
204
+
205
+ const RESEARCH_PROMPT = `You are a research copilot inside SwarmClaw.
206
+
207
+ Primary objective:
208
+ - Gather facts, compare options, summarize findings, and keep the user's work organized.
209
+
210
+ Behavior:
211
+ - Clarify the research question when needed.
212
+ - Prefer structured findings, tradeoffs, and source-backed summaries.
213
+ - Capture useful outputs in files or tasks when that helps the user continue.`
214
+
215
+ const BUILDER_PROMPT = `You are a builder agent inside SwarmClaw.
216
+
217
+ Primary objective:
218
+ - Help the user design, implement, debug, and ship software or technical projects.
219
+
220
+ Behavior:
221
+ - Move from goal to concrete implementation steps quickly.
222
+ - Use code, files, browser, and task tooling when helpful.
223
+ - Surface blockers, assumptions, and verification clearly.`
224
+
225
+ const REVIEWER_PROMPT = `You are a reviewer agent inside SwarmClaw.
226
+
227
+ Primary objective:
228
+ - Review plans, code, documents, and outputs for quality, correctness, and risk.
229
+
230
+ Behavior:
231
+ - Focus first on bugs, regressions, gaps, and unclear assumptions.
232
+ - Be direct and specific.
233
+ - Offer concrete follow-up actions when you find issues.`
234
+
235
+ const WRITER_PROMPT = `You are a writing copilot inside SwarmClaw.
236
+
237
+ Primary objective:
238
+ - Help the user draft, refine, and structure written work for clarity and impact.
239
+
240
+ Behavior:
241
+ - Adapt tone, format, and level of detail to the user's context.
242
+ - Suggest outlines, drafts, revisions, and packaging for different channels.
243
+ - Keep momentum high and avoid generic filler.`
244
+
245
+ const EDITOR_PROMPT = `You are an editor inside SwarmClaw.
246
+
247
+ Primary objective:
248
+ - Improve drafts for clarity, structure, tone, and quality.
249
+
250
+ Behavior:
251
+ - Tighten weak writing, call out inconsistencies, and preserve the intended voice.
252
+ - Give concise, high-signal edits and rationale.
253
+ - Flag missing evidence or unclear claims when relevant.`
254
+
255
+ const OPERATOR_PROMPT = `You are an operations-focused SwarmClaw operator.
256
+
257
+ Primary objective:
258
+ - Keep work moving across agents, tasks, schedules, and approvals without losing sight of the user's real goals.
259
+
260
+ Behavior:
261
+ - Monitor progress, surface bottlenecks, and delegate when appropriate.
262
+ - Be explicit about what is blocked, what is running, and what should happen next.
263
+ - Treat the control plane as a means to an end, not the end itself.`
264
+
265
+ export type OnboardingPath = 'quick' | 'intent' | 'manual'
266
+
267
+ export interface OnboardingPathOption {
268
+ id: OnboardingPath
269
+ title: string
270
+ description: string
271
+ detail: string
272
+ badge?: string
273
+ }
274
+
275
+ export const ONBOARDING_PATHS: OnboardingPathOption[] = [
276
+ {
277
+ id: 'quick',
278
+ title: 'Quick Start',
279
+ description: 'Provider first, one starter kit, fastest path into chat.',
280
+ detail: 'Best when you already know which provider you want and want to get moving quickly.',
281
+ badge: 'Fastest',
282
+ },
283
+ {
284
+ id: 'intent',
285
+ title: 'Intent Guided',
286
+ description: 'Start from what you want to do, then shape a starter workspace around it.',
287
+ detail: 'Best for open-ended use cases like research, building, writing, planning, or mixed personal work.',
288
+ badge: 'Recommended',
289
+ },
290
+ {
291
+ id: 'manual',
292
+ title: 'Custom Setup',
293
+ description: 'Configure providers first and choose whether to start blank or from a template.',
294
+ detail: 'Best for advanced users who want control over the initial setup and agent mix.',
295
+ },
296
+ ]
297
+
298
+ export interface StarterKitAgentTemplate {
299
+ id: string
300
+ name: string
301
+ description: string
302
+ systemPrompt: string
303
+ tools: string[]
304
+ capabilities?: string[]
305
+ recommendedProviders?: SetupProvider[]
306
+ platformAssignScope?: 'self' | 'all'
307
+ }
308
+
309
+ export interface StarterKit {
310
+ id: string
311
+ name: string
312
+ description: string
313
+ detail: string
314
+ badge?: string
315
+ recommendedFor?: OnboardingPath[]
316
+ agents: StarterKitAgentTemplate[]
317
+ }
318
+
319
+ const PERSONAL_AGENT_TOOLS = [
320
+ 'memory',
321
+ 'files',
322
+ 'web_search',
323
+ 'web_fetch',
324
+ 'browser',
325
+ 'manage_tasks',
326
+ 'manage_schedules',
327
+ 'manage_documents',
328
+ ]
329
+
330
+ const RESEARCH_AGENT_TOOLS = [
331
+ 'memory',
332
+ 'files',
333
+ 'web_search',
334
+ 'web_fetch',
335
+ 'browser',
336
+ 'manage_tasks',
337
+ 'manage_documents',
338
+ ]
339
+
340
+ const BUILDER_AGENT_TOOLS = [
341
+ 'memory',
342
+ 'files',
343
+ 'web_search',
344
+ 'web_fetch',
345
+ 'browser',
346
+ 'manage_tasks',
347
+ 'claude_code',
348
+ 'codex_cli',
349
+ 'opencode_cli',
350
+ ]
351
+
352
+ const OPERATOR_AGENT_TOOLS = STARTER_AGENT_TOOLS
353
+ const OPENCLAW_AGENT_TOOLS = [
354
+ 'memory',
355
+ 'files',
356
+ 'web_search',
357
+ 'web_fetch',
358
+ 'browser',
359
+ 'manage_tasks',
360
+ 'manage_schedules',
361
+ 'manage_sessions',
362
+ 'openclaw_workspace',
363
+ ]
364
+
365
+ export const STARTER_KITS: StarterKit[] = [
366
+ {
367
+ id: 'personal_assistant',
368
+ name: 'Personal Assistant',
369
+ description: 'One flexible agent for open-ended work.',
370
+ detail: 'A strong default for general planning, research, writing, and day-to-day execution.',
371
+ badge: 'Recommended',
372
+ recommendedFor: ['quick', 'intent'],
373
+ agents: [
374
+ {
375
+ id: 'sidekick',
376
+ name: 'Sidekick',
377
+ description: 'A versatile assistant for everyday work, planning, and follow-through.',
378
+ systemPrompt: PERSONAL_ASSISTANT_PROMPT,
379
+ tools: PERSONAL_AGENT_TOOLS,
380
+ capabilities: ['planning', 'research', 'writing', 'coordination'],
381
+ },
382
+ ],
383
+ },
384
+ {
385
+ id: 'research_copilot',
386
+ name: 'Research Copilot',
387
+ description: 'A focused setup for investigation and synthesis.',
388
+ detail: 'Useful for market scans, comparisons, technical investigation, and source-backed summaries.',
389
+ recommendedFor: ['intent', 'manual'],
390
+ agents: [
391
+ {
392
+ id: 'researcher',
393
+ name: 'Researcher',
394
+ description: 'Collects facts, compares options, and produces structured findings.',
395
+ systemPrompt: RESEARCH_PROMPT,
396
+ tools: RESEARCH_AGENT_TOOLS,
397
+ capabilities: ['research', 'analysis', 'summarization'],
398
+ },
399
+ ],
400
+ },
401
+ {
402
+ id: 'builder_studio',
403
+ name: 'Builder Studio',
404
+ description: 'Start with a builder and a reviewer.',
405
+ detail: 'Good for coding, prototyping, product work, and technical iteration.',
406
+ recommendedFor: ['intent', 'manual'],
407
+ agents: [
408
+ {
409
+ id: 'builder',
410
+ name: 'Builder',
411
+ description: 'Implements ideas, ships changes, and drives technical execution.',
412
+ systemPrompt: BUILDER_PROMPT,
413
+ tools: BUILDER_AGENT_TOOLS,
414
+ capabilities: ['coding', 'debugging', 'implementation'],
415
+ recommendedProviders: ['anthropic', 'openai', 'google', 'openclaw', 'ollama'],
416
+ },
417
+ {
418
+ id: 'reviewer',
419
+ name: 'Reviewer',
420
+ description: 'Reviews plans and outputs for bugs, regressions, and quality gaps.',
421
+ systemPrompt: REVIEWER_PROMPT,
422
+ tools: RESEARCH_AGENT_TOOLS,
423
+ capabilities: ['review', 'testing', 'risk assessment'],
424
+ recommendedProviders: ['anthropic', 'openai', 'google', 'openclaw'],
425
+ },
426
+ ],
427
+ },
428
+ {
429
+ id: 'content_studio',
430
+ name: 'Content Studio',
431
+ description: 'A writer and editor working together.',
432
+ detail: 'Useful for blogs, marketing copy, docs, newsletters, and publishing workflows.',
433
+ recommendedFor: ['intent', 'manual'],
434
+ agents: [
435
+ {
436
+ id: 'writer',
437
+ name: 'Writer',
438
+ description: 'Drafts content, outlines, and messaging in the user’s preferred style.',
439
+ systemPrompt: WRITER_PROMPT,
440
+ tools: PERSONAL_AGENT_TOOLS,
441
+ capabilities: ['writing', 'messaging', 'structuring'],
442
+ },
443
+ {
444
+ id: 'editor',
445
+ name: 'Editor',
446
+ description: 'Improves structure, tone, and quality before publishing.',
447
+ systemPrompt: EDITOR_PROMPT,
448
+ tools: RESEARCH_AGENT_TOOLS,
449
+ capabilities: ['editing', 'quality control', 'review'],
450
+ },
451
+ ],
452
+ },
453
+ {
454
+ id: 'operator_swarm',
455
+ name: 'Operator Swarm',
456
+ description: 'A coordination-heavy setup for multi-agent work.',
457
+ detail: 'Closest to the current SwarmClaw operator workflow, with an orchestrator plus an execution agent.',
458
+ recommendedFor: ['manual'],
459
+ agents: [
460
+ {
461
+ id: 'operator',
462
+ name: 'Operator',
463
+ description: 'Coordinates tasks, delegates work, and keeps the workspace moving.',
464
+ systemPrompt: OPERATOR_PROMPT,
465
+ tools: OPERATOR_AGENT_TOOLS,
466
+ capabilities: ['coordination', 'delegation', 'operations'],
467
+ platformAssignScope: 'all',
468
+ recommendedProviders: ['openclaw', 'anthropic', 'openai'],
469
+ },
470
+ {
471
+ id: 'maker',
472
+ name: 'Maker',
473
+ description: 'Executes focused work items assigned by the user or other agents.',
474
+ systemPrompt: BUILDER_PROMPT,
475
+ tools: BUILDER_AGENT_TOOLS,
476
+ capabilities: ['execution', 'implementation', 'research'],
477
+ },
478
+ ],
479
+ },
480
+ {
481
+ id: 'openclaw_fleet',
482
+ name: 'OpenClaw Fleet',
483
+ description: 'An OpenClaw-first starter setup for local or remote gateways.',
484
+ detail: 'Designed for users who want multiple OpenClaw-backed agents right away, including remote endpoint assignments.',
485
+ recommendedFor: ['manual'],
486
+ badge: 'OpenClaw',
487
+ agents: [
488
+ {
489
+ id: 'openclaw_operator',
490
+ name: 'OpenClaw Operator',
491
+ description: 'Coordinates OpenClaw-backed execution and keeps distributed agents aligned.',
492
+ systemPrompt: OPERATOR_PROMPT,
493
+ tools: OPERATOR_AGENT_TOOLS,
494
+ capabilities: ['coordination', 'delegation', 'openclaw'],
495
+ platformAssignScope: 'all',
496
+ recommendedProviders: ['openclaw'],
497
+ },
498
+ {
499
+ id: 'openclaw_builder',
500
+ name: 'Remote Builder',
501
+ description: 'A build-focused OpenClaw agent for implementation work on a chosen gateway.',
502
+ systemPrompt: BUILDER_PROMPT,
503
+ tools: OPENCLAW_AGENT_TOOLS,
504
+ capabilities: ['coding', 'implementation', 'openclaw'],
505
+ recommendedProviders: ['openclaw'],
506
+ },
507
+ {
508
+ id: 'openclaw_researcher',
509
+ name: 'Remote Researcher',
510
+ description: 'A research-focused OpenClaw agent for browser and knowledge work on a chosen gateway.',
511
+ systemPrompt: RESEARCH_PROMPT,
512
+ tools: OPENCLAW_AGENT_TOOLS,
513
+ capabilities: ['research', 'analysis', 'openclaw'],
514
+ recommendedProviders: ['openclaw'],
515
+ },
516
+ ],
517
+ },
518
+ {
519
+ id: 'blank_workspace',
520
+ name: 'Blank Workspace',
521
+ description: 'Finish setup without starter agents.',
522
+ detail: 'Use this if you want to land in the app first and create providers, agents, and workflows yourself.',
523
+ recommendedFor: ['manual'],
524
+ badge: 'Blank',
525
+ agents: [],
526
+ },
527
+ ]
528
+
192
529
  export interface DefaultAgentConfig {
193
530
  name: string
194
531
  description: string
@@ -276,3 +613,7 @@ export const DEFAULT_AGENTS: Record<SetupProvider, DefaultAgentConfig> = {
276
613
  tools: STARTER_AGENT_TOOLS,
277
614
  },
278
615
  }
616
+
617
+ export function getDefaultModelForProvider(provider: SetupProvider): string {
618
+ return DEFAULT_AGENTS[provider].model
619
+ }
@@ -16,14 +16,14 @@ export const AVAILABLE_TOOLS: ToolDefinition[] = [
16
16
  { id: 'delegate', label: 'Delegate', description: 'Delegate complex tasks to specialized backends (Claude Code, Codex, OpenCode)' },
17
17
  { id: 'browser', label: 'Browser', description: 'Playwright — browse, scrape, interact with web pages' },
18
18
  { id: 'memory', label: 'Memory', description: 'Store and retrieve long-term memories across conversations' },
19
- { id: 'sandbox', label: 'Sandbox', description: 'Secure isolated code execution for JS, TS, and Python' },
19
+ { id: 'sandbox', label: 'Sandbox', description: 'Deno-based isolated JS/TS execution for cases where custom code is necessary' },
20
20
  { id: 'create_document', label: 'Create Document', description: 'Render markdown to PDF, HTML, or image' },
21
21
  { id: 'create_spreadsheet', label: 'Create Spreadsheet', description: 'Create Excel or CSV files from structured data' },
22
- { id: 'http_request', label: 'HTTP Request', description: 'Make direct HTTP API calls with custom methods, headers, and bodies' },
22
+ { id: 'http_request', label: 'HTTP Request', description: 'Make direct HTTP API calls without generating throwaway code' },
23
23
  { id: 'git', label: 'Git', description: 'Run structured git operations (status, commit, push, diff, etc.)' },
24
24
  { id: 'wallet', label: 'Wallet', description: 'Manage agent crypto wallet — check balance, send SOL, view transactions' },
25
25
  { id: 'monitor', label: 'Monitor', description: 'System observability: check resource usage, watch logs, and ping endpoints' },
26
- { id: 'plugin_creator', label: 'Plugin Creator', description: 'Design, write, and test custom SwarmClaw plugins dynamically' },
26
+ { id: 'plugin_creator', label: 'Plugin Creator', description: 'Design focused plugins for durable capabilities and recurring automations' },
27
27
  { id: 'sample_ui', label: 'Sample UI', description: 'Demonstration of dynamic UI injection into Sidebar and Chat Header' },
28
28
  { id: 'image_gen', label: 'Image Generation', description: 'Generate images from text prompts using OpenAI, Stability AI, Replicate, fal.ai, and more' },
29
29
  { id: 'email', label: 'Email', description: 'Send emails via SMTP with plain text and HTML support' },
@@ -49,4 +49,3 @@ export const ALL_TOOLS: ToolDefinition[] = [...AVAILABLE_TOOLS, ...PLATFORM_TOOL
49
49
  export const TOOL_LABELS: Record<string, string> = Object.fromEntries(
50
50
  ALL_TOOLS.map((t) => [t.id, t.label]),
51
51
  )
52
-
@@ -1,5 +1,18 @@
1
1
  import { z } from 'zod'
2
2
 
3
+ const AgentRoutingTargetSchema = z.object({
4
+ id: z.string().min(1),
5
+ label: z.string().optional(),
6
+ role: z.enum(['primary', 'economy', 'premium', 'reasoning', 'backup']).optional(),
7
+ provider: z.string().min(1),
8
+ model: z.string().optional().default(''),
9
+ credentialId: z.string().nullable().optional().default(null),
10
+ fallbackCredentialIds: z.array(z.string()).optional().default([]),
11
+ apiEndpoint: z.string().nullable().optional().default(null),
12
+ gatewayProfileId: z.string().nullable().optional().default(null),
13
+ priority: z.number().int().optional(),
14
+ })
15
+
3
16
  export const AgentCreateSchema = z.object({
4
17
  name: z.string().min(1, 'Agent name is required'),
5
18
  provider: z.string().min(1, 'Provider is required'),
@@ -7,22 +20,41 @@ export const AgentCreateSchema = z.object({
7
20
  systemPrompt: z.string().optional().default(''),
8
21
  model: z.string().optional().default(''),
9
22
  credentialId: z.string().nullable().optional().default(null),
23
+ fallbackCredentialIds: z.array(z.string()).optional().default([]),
10
24
  apiEndpoint: z.string().nullable().optional().default(null),
25
+ gatewayProfileId: z.string().nullable().optional().default(null),
26
+ routingStrategy: z.enum(['single', 'balanced', 'economy', 'premium', 'reasoning']).nullable().optional().default(null),
27
+ routingTargets: z.array(AgentRoutingTargetSchema).optional().default([]),
11
28
  isOrchestrator: z.boolean().optional().default(false),
12
29
  platformAssignScope: z.enum(['self', 'all']).optional().default('self'),
13
30
  subAgentIds: z.array(z.string()).optional().default([]),
14
31
  plugins: z.array(z.string()).optional().default([]),
15
32
  /** @deprecated Use plugins */
16
33
  tools: z.array(z.string()).optional(),
34
+ skills: z.array(z.string()).optional().default([]),
35
+ skillIds: z.array(z.string()).optional().default([]),
36
+ mcpServerIds: z.array(z.string()).optional().default([]),
37
+ mcpDisabledTools: z.array(z.string()).optional().default([]),
17
38
  capabilities: z.array(z.string()).optional().default([]),
18
39
  thinkingLevel: z.string().optional(),
19
40
  soul: z.string().optional(),
20
41
  identityState: z.record(z.string(), z.unknown()).nullable().optional().default(null),
42
+ heartbeatEnabled: z.boolean().optional().default(false),
43
+ heartbeatInterval: z.union([z.string(), z.number()]).nullable().optional().default(null),
44
+ heartbeatIntervalSec: z.number().int().nonnegative().nullable().optional().default(null),
45
+ heartbeatModel: z.string().nullable().optional().default(null),
46
+ heartbeatPrompt: z.string().nullable().optional().default(null),
47
+ elevenLabsVoiceId: z.string().nullable().optional().default(null),
21
48
  sessionResetMode: z.enum(['idle', 'daily']).nullable().optional().default(null),
22
49
  sessionIdleTimeoutSec: z.number().int().nonnegative().nullable().optional().default(null),
23
50
  sessionMaxAgeSec: z.number().int().nonnegative().nullable().optional().default(null),
24
51
  sessionDailyResetAt: z.string().nullable().optional().default(null),
25
52
  sessionResetTimezone: z.string().nullable().optional().default(null),
53
+ memoryScopeMode: z.enum(['auto', 'all', 'global', 'agent', 'session', 'project']).nullable().optional().default(null),
54
+ memoryTierPreference: z.enum(['working', 'durable', 'archive', 'blended']).nullable().optional().default(null),
55
+ projectId: z.string().optional(),
56
+ avatarSeed: z.string().optional(),
57
+ avatarUrl: z.string().nullable().optional().default(null),
26
58
  autoRecovery: z.boolean().optional().default(false),
27
59
  monthlyBudget: z.number().positive().nullable().optional().default(null),
28
60
  dailyBudget: z.number().positive().nullable().optional().default(null),
@@ -43,6 +75,28 @@ export const ConnectorCreateSchema = z.object({
43
75
  autoStart: z.boolean().optional(),
44
76
  })
45
77
 
78
+ export const ExternalAgentRegisterSchema = z.object({
79
+ id: z.string().optional(),
80
+ name: z.string().min(1, 'External agent name is required'),
81
+ sourceType: z.enum(['codex', 'claude', 'opencode', 'openclaw', 'custom']).default('custom'),
82
+ status: z.enum(['online', 'idle', 'offline', 'stale']).optional().default('online'),
83
+ provider: z.string().nullable().optional().default(null),
84
+ model: z.string().nullable().optional().default(null),
85
+ workspace: z.string().nullable().optional().default(null),
86
+ transport: z.enum(['http', 'ws', 'cli', 'gateway', 'custom']).nullable().optional().default(null),
87
+ endpoint: z.string().nullable().optional().default(null),
88
+ agentId: z.string().nullable().optional().default(null),
89
+ gatewayProfileId: z.string().nullable().optional().default(null),
90
+ capabilities: z.array(z.string()).optional().default([]),
91
+ labels: z.array(z.string()).optional().default([]),
92
+ metadata: z.record(z.string(), z.unknown()).nullable().optional().default(null),
93
+ tokenStats: z.object({
94
+ inputTokens: z.number().nonnegative().optional(),
95
+ outputTokens: z.number().nonnegative().optional(),
96
+ totalTokens: z.number().nonnegative().optional(),
97
+ }).nullable().optional().default(null),
98
+ })
99
+
46
100
  export const TaskCreateSchema = z.object({
47
101
  title: z.string().min(1, 'Task title is required'),
48
102
  description: z.string().optional().default(''),
@@ -71,7 +125,7 @@ export const TaskCreateSchema = z.object({
71
125
 
72
126
  export const ChatroomCreateSchema = z.object({
73
127
  name: z.string().min(1, 'Chatroom name is required'),
74
- agentIds: z.array(z.string()).default([]),
128
+ agentIds: z.array(z.string()).min(1, 'Select at least one agent').default([]),
75
129
  description: z.string().optional().default(''),
76
130
  chatMode: z.enum(['sequential', 'parallel']).optional(),
77
131
  autoAddress: z.boolean().optional(),
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import { create } from 'zustand'
4
- import type { Sessions, Session, NetworkInfo, Directory, ProviderInfo, Credentials, Agent, Schedule, AppView, BoardTask, AppSettings, OrchestratorSecret, ProviderConfig, Skill, Connector, Webhook, McpServerConfig, PluginMeta, Project, FleetFilter, ActivityEntry, AppNotification, ApprovalRequest } from '../types'
4
+ import type { Sessions, Session, NetworkInfo, Directory, ProviderInfo, Credentials, Agent, Schedule, AppView, BoardTask, AppSettings, OrchestratorSecret, ProviderConfig, Skill, Connector, Webhook, McpServerConfig, PluginMeta, Project, FleetFilter, ActivityEntry, AppNotification, ApprovalRequest, GatewayProfile, ExternalAgentRuntime } from '../types'
5
5
  import { fetchChats, fetchDirs, fetchProviders, fetchCredentials } from '../lib/chats'
6
6
  import { fetchAgents } from '../lib/agents'
7
7
  import { fetchSchedules } from '../lib/schedules'
@@ -76,6 +76,10 @@ interface AppState {
76
76
  triggerMemoryRefresh: () => void
77
77
  memoryAgentFilter: string | null
78
78
  setMemoryAgentFilter: (agentId: string | null) => void
79
+ memoryTierFilter: 'all' | 'working' | 'durable' | 'archive'
80
+ setMemoryTierFilter: (tier: 'all' | 'working' | 'durable' | 'archive') => void
81
+ memoryScopeFilter: 'all' | 'global' | 'agent' | 'session' | 'project'
82
+ setMemoryScopeFilter: (scope: 'all' | 'global' | 'agent' | 'session' | 'project') => void
79
83
 
80
84
  appSettings: AppSettings
81
85
  loadSettings: () => Promise<void>
@@ -109,6 +113,13 @@ interface AppState {
109
113
  editingProviderId: string | null
110
114
  setEditingProviderId: (id: string | null) => void
111
115
 
116
+ gatewayProfiles: GatewayProfile[]
117
+ loadGatewayProfiles: () => Promise<void>
118
+ gatewaySheetOpen: boolean
119
+ setGatewaySheetOpen: (open: boolean) => void
120
+ editingGatewayId: string | null
121
+ setEditingGatewayId: (id: string | null) => void
122
+
112
123
  // Skills
113
124
  skills: Record<string, Skill>
114
125
  loadSkills: () => Promise<void>
@@ -212,6 +223,9 @@ interface AppState {
212
223
  walletPanelAgentId: string | null
213
224
  setWalletPanelAgentId: (id: string | null) => void
214
225
 
226
+ externalAgents: ExternalAgentRuntime[]
227
+ loadExternalAgents: () => Promise<void>
228
+
215
229
  }
216
230
 
217
231
  export const useAppStore = create<AppState>((set, get) => ({
@@ -394,6 +408,10 @@ export const useAppStore = create<AppState>((set, get) => ({
394
408
  triggerMemoryRefresh: () => set((s) => ({ memoryRefreshKey: s.memoryRefreshKey + 1 })),
395
409
  memoryAgentFilter: null,
396
410
  setMemoryAgentFilter: (agentId) => set({ memoryAgentFilter: agentId }),
411
+ memoryTierFilter: 'all',
412
+ setMemoryTierFilter: (tier) => set({ memoryTierFilter: tier }),
413
+ memoryScopeFilter: 'all',
414
+ setMemoryScopeFilter: (scope) => set({ memoryScopeFilter: scope }),
397
415
 
398
416
  appSettings: {},
399
417
  loadSettings: async () => {
@@ -490,6 +508,20 @@ export const useAppStore = create<AppState>((set, get) => ({
490
508
  editingProviderId: null,
491
509
  setEditingProviderId: (id) => set({ editingProviderId: id }),
492
510
 
511
+ gatewayProfiles: [],
512
+ loadGatewayProfiles: async () => {
513
+ try {
514
+ const gatewayProfiles = await api<GatewayProfile[]>('GET', '/gateways')
515
+ set({ gatewayProfiles })
516
+ } catch {
517
+ // ignore
518
+ }
519
+ },
520
+ gatewaySheetOpen: false,
521
+ setGatewaySheetOpen: (open) => set({ gatewaySheetOpen: open }),
522
+ editingGatewayId: null,
523
+ setEditingGatewayId: (id) => set({ editingGatewayId: id }),
524
+
493
525
  // Skills
494
526
  skills: {},
495
527
  loadSkills: async () => {
@@ -712,4 +744,14 @@ export const useAppStore = create<AppState>((set, get) => ({
712
744
  walletPanelAgentId: null,
713
745
  setWalletPanelAgentId: (id) => set({ walletPanelAgentId: id }),
714
746
 
747
+ externalAgents: [],
748
+ loadExternalAgents: async () => {
749
+ try {
750
+ const externalAgents = await api<ExternalAgentRuntime[]>('GET', '/external-agents')
751
+ set({ externalAgents })
752
+ } catch {
753
+ // ignore
754
+ }
755
+ },
756
+
715
757
  }))