@swarmclawai/swarmclaw 1.1.1 → 1.1.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.
- package/README.md +188 -6
- package/package.json +1 -1
- package/src/app/api/agents/[id]/route.ts +29 -0
- package/src/app/api/agents/route.ts +16 -0
- package/src/app/api/agents/thread-route.test.ts +3 -3
- package/src/app/api/autonomy/estop/route.ts +1 -1
- package/src/app/api/chatrooms/[id]/chat/route.test.ts +6 -6
- package/src/app/api/chats/[id]/chat/route.test.ts +23 -23
- package/src/app/api/chats/[id]/messages/route.ts +4 -5
- package/src/app/api/chats/[id]/route.ts +5 -0
- package/src/app/api/chats/messages-route.test.ts +65 -0
- package/src/app/api/chats/route.ts +1 -0
- package/src/app/api/credentials/[id]/route.ts +2 -3
- package/src/app/api/daemon/route.ts +1 -1
- package/src/app/api/extensions/builtins/route.ts +40 -0
- package/src/app/api/extensions/dependencies/route.ts +3 -3
- package/src/app/api/extensions/install/route.ts +19 -19
- package/src/app/api/extensions/marketplace/route.ts +18 -22
- package/src/app/api/extensions/route.ts +13 -13
- package/src/app/api/extensions/settings/route.ts +19 -19
- package/src/app/api/extensions/ui/route.ts +3 -3
- package/src/app/api/memory/maintenance/route.ts +51 -41
- package/src/app/api/providers/[id]/discover-models/route.ts +1 -0
- package/src/app/api/schedules/[id]/route.test.ts +1 -1
- package/src/app/api/schedules/route.test.ts +1 -1
- package/src/app/api/setup/check-provider/route.ts +27 -9
- package/src/app/api/setup/doctor/route.ts +7 -7
- package/src/app/api/tasks/[id]/route.ts +9 -7
- package/src/app/api/tasks/route.ts +5 -5
- package/src/app/api/usage/route.ts +16 -16
- package/src/app/api/webhooks/[id]/helpers.ts +4 -3
- package/src/app/autonomy/page.tsx +136 -3
- package/src/app/chatrooms/page.tsx +38 -16
- package/src/app/extensions/layout.tsx +3 -3
- package/src/app/extensions/page.tsx +3 -3
- package/src/app/protocols/page.tsx +177 -10
- package/src/app/usage/page.tsx +8 -8
- package/src/cli/index.js +3 -2
- package/src/cli/spec.js +2 -2
- package/src/components/agents/agent-sheet.tsx +193 -39
- package/src/components/auth/setup-wizard/index.tsx +6 -0
- package/src/components/auth/setup-wizard/step-agents.tsx +35 -0
- package/src/components/auth/setup-wizard/types.ts +2 -0
- package/src/components/auth/setup-wizard/utils.ts +2 -0
- package/src/components/chat/chat-area.tsx +10 -10
- package/src/components/chat/chat-header.tsx +1 -0
- package/src/components/chat/chat-tool-toggles.tsx +80 -39
- package/src/components/chat/file-path-chip.tsx +4 -3
- package/src/components/chat/message-bubble.test.ts +124 -3
- package/src/components/chat/message-bubble.tsx +195 -106
- package/src/components/chat/message-list.tsx +111 -80
- package/src/components/chat/tool-request-banner.tsx +17 -17
- package/src/components/chatrooms/chatroom-list.tsx +11 -8
- package/src/components/connectors/connector-sheet.tsx +5 -5
- package/src/components/{plugins/plugin-list.tsx → extensions/extension-list.tsx} +84 -84
- package/src/components/{plugins/plugin-sheet.tsx → extensions/extension-sheet.tsx} +59 -59
- package/src/components/input/chat-input.tsx +23 -17
- package/src/components/layout/dashboard-shell.tsx +4 -4
- package/src/components/layout/sheet-layer.tsx +2 -2
- package/src/components/mcp-servers/mcp-server-list.tsx +1 -1
- package/src/components/protocols/structured-session-launcher.tsx +1 -0
- package/src/components/shared/model-combobox.tsx +6 -3
- package/src/components/tasks/task-column.tsx +1 -0
- package/src/components/tasks/task-list.tsx +1 -0
- package/src/instrumentation.ts +1 -1
- package/src/lib/agent-default-tools.test.ts +24 -30
- package/src/lib/app/api-client.test.ts +3 -3
- package/src/lib/canvas-content.test.ts +1 -1
- package/src/lib/capability-selection.test.ts +1 -1
- package/src/lib/chat/chat-streaming-state.test.ts +3 -6
- package/src/lib/chat/chat-streaming-state.ts +6 -6
- package/src/lib/chat/message-list-utils.test.ts +31 -0
- package/src/lib/chat/message-list-utils.ts +5 -0
- package/src/lib/chat/queued-message-queue.ts +12 -1
- package/src/lib/{plugin-install-cors.ts → extension-install-cors.ts} +4 -4
- package/src/lib/{plugin-sources.ts → extension-sources.ts} +17 -17
- package/src/lib/keyed-queue.test.ts +52 -0
- package/src/lib/keyed-queue.ts +33 -0
- package/src/lib/ollama-mode.test.ts +33 -0
- package/src/lib/ollama-mode.ts +28 -0
- package/src/lib/orchestrator-config.test.ts +45 -0
- package/src/lib/orchestrator-config.ts +72 -0
- package/src/lib/plugin-sources.test.ts +18 -18
- package/src/lib/provider-model-discovery-client.ts +2 -0
- package/src/lib/providers/anthropic.ts +5 -4
- package/src/lib/providers/error-classification.test.ts +35 -0
- package/src/lib/providers/error-classification.ts +70 -0
- package/src/lib/providers/index.ts +52 -27
- package/src/lib/providers/ollama.ts +7 -5
- package/src/lib/providers/openai.ts +51 -25
- package/src/lib/server/agents/agent-runtime-config.test.ts +37 -1
- package/src/lib/server/agents/agent-runtime-config.ts +10 -0
- package/src/lib/server/agents/agent-thread-session.test.ts +9 -5
- package/src/lib/server/agents/agent-thread-session.ts +1 -0
- package/src/lib/server/agents/subagent-runtime.test.ts +57 -53
- package/src/lib/server/agents/subagent-runtime.ts +19 -19
- package/src/lib/server/agents/subagent-swarm.ts +59 -4
- package/src/lib/server/approval-match.ts +4 -4
- package/src/lib/server/approvals.ts +3 -2
- package/src/lib/server/autonomy/supervisor-reflection.ts +71 -2
- package/src/lib/server/build-llm.test.ts +65 -2
- package/src/lib/server/build-llm.ts +17 -5
- package/src/lib/server/{builtin-plugins.ts → builtin-extensions.ts} +2 -9
- package/src/lib/server/capability-router.ts +9 -9
- package/src/lib/server/chat-execution/chat-execution-advanced.test.ts +5 -5
- package/src/lib/server/chat-execution/chat-execution-disabled.test.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution-eval-history.test.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution-heartbeat.test.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution-session-sync.test.ts +15 -15
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +4 -4
- package/src/lib/server/chat-execution/chat-execution-utils.ts +3 -9
- package/src/lib/server/chat-execution/chat-execution.ts +52 -49
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +6 -6
- package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +14 -14
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +10 -10
- package/src/lib/server/chat-execution/memory-mutation-tools.ts +2 -2
- package/src/lib/server/chat-execution/situational-awareness.test.ts +5 -5
- package/src/lib/server/chat-execution/situational-awareness.ts +137 -1
- package/src/lib/server/chat-execution/stream-agent-chat.test.ts +11 -11
- package/src/lib/server/chat-execution/stream-agent-chat.ts +85 -84
- package/src/lib/server/chat-execution/stream-continuation.ts +4 -4
- package/src/lib/server/chatrooms/chatroom-helpers.test.ts +1 -0
- package/src/lib/server/chatrooms/chatroom-helpers.ts +3 -1
- package/src/lib/server/chatrooms/chatroom-session-persistence.test.ts +3 -3
- package/src/lib/server/chatrooms/mailbox-utils.ts +5 -5
- package/src/lib/server/chatrooms/session-mailbox.test.ts +6 -0
- package/src/lib/server/connectors/inbound-audio-transcription.test.ts +5 -5
- package/src/lib/server/connectors/manager-roundtrip.test.ts +14 -14
- package/src/lib/server/connectors/manager.test.ts +142 -142
- package/src/lib/server/connectors/manager.ts +11 -8
- package/src/lib/server/connectors/outbox.test.ts +11 -11
- package/src/lib/server/connectors/session.test.ts +10 -10
- package/src/lib/server/cost.ts +9 -9
- package/src/lib/server/data-dir.test.ts +8 -8
- package/src/lib/server/eval/agent-regression-advanced.test.ts +66 -66
- package/src/lib/server/eval/agent-regression.test.ts +7 -7
- package/src/lib/server/eval/agent-regression.ts +104 -103
- package/src/lib/server/{plugins-approval-guidance.ts → extensions-approval-guidance.ts} +31 -31
- package/src/lib/server/{plugins.test.ts → extensions.test.ts} +104 -105
- package/src/lib/server/{plugins.ts → extensions.ts} +501 -483
- package/src/lib/server/integrity-monitor.test.ts +21 -21
- package/src/lib/server/integrity-monitor.ts +10 -6
- package/src/lib/server/knowledge-db.test.ts +4 -0
- package/src/lib/server/langgraph-checkpoint.test.ts +6 -6
- package/src/lib/server/langgraph-checkpoint.ts +6 -1
- package/src/lib/server/memory/memory-consolidation.ts +122 -3
- package/src/lib/server/memory/memory-db.ts +10 -1
- package/src/lib/server/memory/memory-integration.test.ts +11 -14
- package/src/lib/server/native-capabilities.test.ts +7 -7
- package/src/lib/server/native-capabilities.ts +85 -85
- package/src/lib/server/ollama-runtime.test.ts +41 -0
- package/src/lib/server/ollama-runtime.ts +13 -18
- package/src/lib/server/openclaw/sync.ts +15 -15
- package/src/lib/server/plugins-advanced.test.ts +86 -87
- package/src/lib/server/protocols/dag-scheduler.ts +103 -0
- package/src/lib/server/protocols/protocol-service.ts +1205 -33
- package/src/lib/server/protocols/step-dag-validation.ts +86 -0
- package/src/lib/server/protocols/step-outputs.ts +57 -0
- package/src/lib/server/provider-endpoint.ts +15 -2
- package/src/lib/server/provider-health.ts +32 -2
- package/src/lib/server/provider-model-discovery.test.ts +23 -0
- package/src/lib/server/provider-model-discovery.ts +23 -5
- package/src/lib/server/runtime/daemon-state-connectors.test.ts +10 -10
- package/src/lib/server/runtime/daemon-state.test.ts +18 -18
- package/src/lib/server/runtime/daemon-state.ts +63 -8
- package/src/lib/server/runtime/heartbeat-service-timer.test.ts +16 -13
- package/src/lib/server/runtime/heartbeat-service.ts +387 -49
- package/src/lib/server/runtime/idle-window.ts +84 -0
- package/src/lib/server/runtime/orchestrator-events.ts +18 -0
- package/src/lib/server/runtime/queue-followups.test.ts +2 -2
- package/src/lib/server/runtime/queue.test.ts +3 -3
- package/src/lib/server/runtime/queue.ts +245 -44
- package/src/lib/server/runtime/scheduler.test.ts +4 -0
- package/src/lib/server/runtime/scheduler.ts +3 -2
- package/src/lib/server/runtime/session-run-manager.test.ts +9 -0
- package/src/lib/server/runtime/system-events.ts +35 -0
- package/src/lib/server/runtime/wake-dispatcher.ts +9 -9
- package/src/lib/server/runtime/watch-jobs.ts +5 -3
- package/src/lib/server/schedules/schedule-lifecycle.test.ts +1 -1
- package/src/lib/server/session-tools/autonomy-tools.test.ts +11 -33
- package/src/lib/server/session-tools/canvas.ts +7 -7
- package/src/lib/server/session-tools/chatroom.ts +31 -8
- package/src/lib/server/session-tools/connector.test.ts +2 -2
- package/src/lib/server/session-tools/connector.ts +7 -7
- package/src/lib/server/session-tools/context-mgmt.ts +7 -7
- package/src/lib/server/session-tools/context.ts +5 -5
- package/src/lib/server/session-tools/crud.test.ts +5 -5
- package/src/lib/server/session-tools/crud.ts +4 -242
- package/src/lib/server/session-tools/delegate-fallback.test.ts +16 -16
- package/src/lib/server/session-tools/delegate.ts +14 -14
- package/src/lib/server/session-tools/discovery-approvals.test.ts +2 -2
- package/src/lib/server/session-tools/discovery.ts +43 -45
- package/src/lib/server/session-tools/edit_file.ts +8 -8
- package/src/lib/server/session-tools/email.ts +11 -11
- package/src/lib/server/session-tools/{plugin-creator.ts → extension-creator.ts} +61 -60
- package/src/lib/server/session-tools/file.ts +9 -9
- package/src/lib/server/session-tools/google-workspace.test.ts +5 -5
- package/src/lib/server/session-tools/google-workspace.ts +11 -10
- package/src/lib/server/session-tools/http.ts +9 -9
- package/src/lib/server/session-tools/human-loop.ts +7 -7
- package/src/lib/server/session-tools/image-gen.ts +20 -20
- package/src/lib/server/session-tools/index.test.ts +8 -0
- package/src/lib/server/session-tools/index.ts +48 -65
- package/src/lib/server/session-tools/mailbox.ts +7 -7
- package/src/lib/server/session-tools/manage-connectors.test.ts +2 -2
- package/src/lib/server/session-tools/manage-schedules-advanced.test.ts +1 -1
- package/src/lib/server/session-tools/manage-schedules.test.ts +11 -11
- package/src/lib/server/session-tools/manage-skills.test.ts +5 -5
- package/src/lib/server/session-tools/manage-tasks-advanced.test.ts +3 -3
- package/src/lib/server/session-tools/manage-tasks.test.ts +1 -1
- package/src/lib/server/session-tools/memory.ts +22 -15
- package/src/lib/server/session-tools/monitor.ts +14 -77
- package/src/lib/server/session-tools/openclaw-nodes.ts +8 -8
- package/src/lib/server/session-tools/openclaw-workspace.ts +7 -7
- package/src/lib/server/session-tools/platform-access.test.ts +4 -4
- package/src/lib/server/session-tools/platform.ts +19 -19
- package/src/lib/server/session-tools/primitive-tools.test.ts +3 -124
- package/src/lib/server/session-tools/replicate.ts +9 -9
- package/src/lib/server/session-tools/sandbox.ts +6 -86
- package/src/lib/server/session-tools/schedule.ts +10 -9
- package/src/lib/server/session-tools/session-info.ts +16 -20
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +13 -38
- package/src/lib/server/session-tools/shell.ts +37 -13
- package/src/lib/server/session-tools/skill-runtime.test.ts +3 -3
- package/src/lib/server/session-tools/skill-runtime.ts +9 -9
- package/src/lib/server/session-tools/skills.ts +4 -4
- package/src/lib/server/session-tools/subagent.ts +7 -7
- package/src/lib/server/session-tools/wallet-tool.test.ts +4 -4
- package/src/lib/server/session-tools/wallet.ts +9 -9
- package/src/lib/server/session-tools/web-browser-config.test.ts +4 -3
- package/src/lib/server/session-tools/web-utils.ts +4 -2
- package/src/lib/server/session-tools/web.ts +68 -15
- package/src/lib/server/skills/clawhub-client.test.ts +2 -2
- package/src/lib/server/skills/discovered-skill-prompt.test.ts +10 -10
- package/src/lib/server/skills/discovered-skill-prompt.ts +10 -10
- package/src/lib/server/skills/learned-skills.ts +54 -2
- package/src/lib/server/skills/runtime-skill-resolver.test.ts +3 -3
- package/src/lib/server/skills/runtime-skill-resolver.ts +24 -24
- package/src/lib/server/skills/skill-suggestions.test.ts +1 -1
- package/src/lib/server/storage-item-access.test.ts +109 -1
- package/src/lib/server/storage.ts +35 -8
- package/src/lib/server/tasks/task-followups.test.ts +21 -11
- package/src/lib/server/tool-aliases.ts +37 -43
- package/src/lib/server/tool-capability-policy-advanced.test.ts +108 -108
- package/src/lib/server/tool-capability-policy.test.ts +13 -13
- package/src/lib/server/tool-capability-policy.ts +32 -37
- package/src/lib/server/tool-loop-detection.ts +5 -5
- package/src/lib/server/tool-planning.test.ts +8 -8
- package/src/lib/server/tool-planning.ts +21 -21
- package/src/lib/server/tool-retry.ts +2 -2
- package/src/lib/server/universal-tool-access.ts +11 -18
- package/src/lib/setup-defaults.ts +38 -0
- package/src/lib/shared-utils.ts +10 -0
- package/src/lib/tool-definitions.ts +16 -16
- package/src/lib/validation/schemas.test.ts +20 -0
- package/src/lib/validation/schemas.ts +114 -20
- package/src/proxy.test.ts +2 -2
- package/src/proxy.ts +12 -12
- package/src/stores/slices/data-slice.ts +4 -4
- package/src/stores/slices/ui-slice.ts +8 -8
- package/src/stores/use-app-store.test.ts +2 -2
- package/src/stores/use-chat-store.test.ts +3 -3
- package/src/stores/use-chat-store.ts +22 -8
- package/src/stores/use-chatroom-store.ts +7 -3
- package/src/types/index.ts +230 -63
- package/src/views/settings/{plugin-manager.tsx → extension-manager.tsx} +36 -36
- package/src/lib/server/session-tools/calendar.ts +0 -367
- package/src/lib/server/session-tools/crawl.ts +0 -449
- package/src/lib/server/session-tools/document.ts +0 -285
- package/src/lib/server/session-tools/extract.ts +0 -139
- package/src/lib/server/session-tools/git.ts +0 -111
- package/src/lib/server/session-tools/table.ts +0 -589
package/README.md
CHANGED
|
@@ -8,15 +8,196 @@
|
|
|
8
8
|
<img src="https://raw.githubusercontent.com/swarmclawai/swarmclaw/main/public/branding/swarmclaw-org-avatar.png" alt="SwarmClaw lobster logo" width="120" />
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
SwarmClaw is a self-hosted AI runtime for OpenClaw and multi-agent work. It helps you run autonomous agents with heartbeats, schedules, delegation, memory, runtime skills, and reviewed conversation-to-skill learning across OpenClaw gateways and other providers.
|
|
11
|
+
SwarmClaw is a self-hosted AI runtime for OpenClaw and multi-agent work. It helps you run autonomous agents and orchestrators with heartbeats, schedules, delegation, memory, runtime skills, and reviewed conversation-to-skill learning across OpenClaw gateways and other providers.
|
|
12
12
|
|
|
13
13
|
GitHub: https://github.com/swarmclawai/swarmclaw
|
|
14
14
|
Docs: https://swarmclaw.ai/docs
|
|
15
15
|
Website: https://swarmclaw.ai
|
|
16
16
|
Extension tutorial: https://swarmclaw.ai/docs/extension-tutorial
|
|
17
17
|
|
|
18
|
+
<div align="center">
|
|
19
|
+
<table>
|
|
20
|
+
<tr>
|
|
21
|
+
<td align="center"><strong>Works<br>with</strong></td>
|
|
22
|
+
<td align="center"><img src="doc/assets/logos/openclaw.svg" width="32" alt="OpenClaw"><br><sub>OpenClaw</sub></td>
|
|
23
|
+
<td align="center"><img src="doc/assets/logos/claude-code.svg" width="32" alt="Claude Code"><br><sub>Claude Code</sub></td>
|
|
24
|
+
<td align="center"><img src="doc/assets/logos/codex.svg" width="32" alt="Codex"><br><sub>Codex</sub></td>
|
|
25
|
+
<td align="center"><img src="doc/assets/logos/gemini-cli.svg" width="32" alt="Gemini CLI"><br><sub>Gemini CLI</sub></td>
|
|
26
|
+
<td align="center"><img src="doc/assets/logos/opencode.svg" width="32" alt="OpenCode"><br><sub>OpenCode</sub></td>
|
|
27
|
+
<td align="center"><img src="doc/assets/logos/anthropic.svg" width="32" alt="Anthropic"><br><sub>Anthropic</sub></td>
|
|
28
|
+
<td align="center"><img src="doc/assets/logos/openai.svg" width="32" alt="OpenAI"><br><sub>OpenAI</sub></td>
|
|
29
|
+
<td align="center"><img src="doc/assets/logos/google.svg" width="32" alt="Google Gemini"><br><sub>Gemini</sub></td>
|
|
30
|
+
<td align="center"><img src="doc/assets/logos/ollama.svg" width="32" alt="Ollama"><br><sub>Ollama</sub></td>
|
|
31
|
+
<td align="center"><img src="doc/assets/logos/deepseek.svg" width="32" alt="DeepSeek"><br><sub>DeepSeek</sub></td>
|
|
32
|
+
<td align="center"><img src="doc/assets/logos/groq.svg" width="32" alt="Groq"><br><sub>Groq</sub></td>
|
|
33
|
+
<td align="center"><img src="doc/assets/logos/together.svg" width="32" alt="Together AI"><br><sub>Together</sub></td>
|
|
34
|
+
<td align="center"><img src="doc/assets/logos/mistral.svg" width="32" alt="Mistral AI"><br><sub>Mistral</sub></td>
|
|
35
|
+
<td align="center"><img src="doc/assets/logos/xai.svg" width="32" alt="xAI"><br><sub>xAI</sub></td>
|
|
36
|
+
<td align="center"><img src="doc/assets/logos/fireworks.svg" width="32" alt="Fireworks AI"><br><sub>Fireworks</sub></td>
|
|
37
|
+
<td align="center"><img src="doc/assets/logos/nebius.svg" width="32" alt="Nebius"><br><sub>Nebius</sub></td>
|
|
38
|
+
<td align="center"><img src="doc/assets/logos/deepinfra.svg" width="32" alt="DeepInfra"><br><sub>DeepInfra</sub></td>
|
|
39
|
+
</tr>
|
|
40
|
+
</table>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
## Use Cases
|
|
44
|
+
|
|
45
|
+
SwarmClaw is a general-purpose agent runtime. Here are some of the ways people use it.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### Personal Assistant
|
|
50
|
+
|
|
51
|
+
A single agent with memory, web access, scheduling, and file tools — your always-available copilot.
|
|
52
|
+
|
|
53
|
+
> *"Remember that I prefer window seats. Book research time every Monday at 9am. Summarize the articles I saved last week."*
|
|
54
|
+
|
|
55
|
+
- Remembers preferences, contacts, and decisions across conversations
|
|
56
|
+
- Schedules reminders, recurring check-ins, and follow-ups
|
|
57
|
+
- Researches, drafts, plans, and manages your day-to-day
|
|
58
|
+
- Bridges to WhatsApp or Telegram so you can message your agent on the go
|
|
59
|
+
|
|
60
|
+
**Starter kit:** Personal Assistant → 1 agent, ready in under a minute.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### Virtual Company
|
|
65
|
+
|
|
66
|
+
Build a full org chart of specialized agents that collaborate, delegate, and report up — a lightweight simulation of a real company.
|
|
67
|
+
|
|
68
|
+
| Role | Agent | Responsibilities |
|
|
69
|
+
|------|-------|-----------------|
|
|
70
|
+
| **CEO** | Strategist | Sets objectives, reviews progress, delegates to department heads |
|
|
71
|
+
| **CTO** | Builder | Owns technical execution, code reviews, architecture decisions |
|
|
72
|
+
| **CFO** | Analyst | Tracks budgets, monitors token spend, produces cost reports |
|
|
73
|
+
| **CMO** | Marketer | Drafts campaigns, manages content calendar, monitors channels |
|
|
74
|
+
| **COO** | Operator | Coordinates cross-agent work, manages schedules, unblocks tasks |
|
|
75
|
+
|
|
76
|
+
- Each agent has its own provider, model, personality (soul), and tool access
|
|
77
|
+
- The CEO delegates via the task board; department heads pick up work autonomously
|
|
78
|
+
- Heartbeat loops let agents check in on their own, surface blockers, and request approvals
|
|
79
|
+
- Memory means every agent remembers past decisions and context
|
|
80
|
+
- Connect the CMO to Discord/Slack so it can post updates directly
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### Development Team
|
|
85
|
+
|
|
86
|
+
A squad of agents mirroring a real engineering team — planning, building, reviewing, and testing in parallel.
|
|
87
|
+
|
|
88
|
+
| Role | Agent | Tools |
|
|
89
|
+
|------|-------|-------|
|
|
90
|
+
| **Lead** | Architect | Delegation, tasks, schedules, missions |
|
|
91
|
+
| **Dev** | Builder | Shell, files, Claude Code / Codex / OpenCode |
|
|
92
|
+
| **QA** | Tester | Shell, browser, files, web search |
|
|
93
|
+
| **Designer** | Creative | Image generation, browser, web search, files |
|
|
94
|
+
| **Reviewer** | Critic | Files, web search, memory |
|
|
95
|
+
|
|
96
|
+
- The Lead creates missions and breaks them into tasks on the board
|
|
97
|
+
- Dev agents pick up tasks and delegate to Claude Code, Codex, or OpenCode for implementation
|
|
98
|
+
- QA runs tests, takes screenshots, and files bugs back on the task board
|
|
99
|
+
- The Reviewer audits PRs and flags regressions
|
|
100
|
+
- Structured Sessions let you run a bounded sprint — plan → build → test → review — with durable transcripts
|
|
101
|
+
|
|
102
|
+
**Starter kit:** Builder Studio → pre-configured Builder + Reviewer pair.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### Research Bureau
|
|
107
|
+
|
|
108
|
+
Multiple research agents working in parallel, each with different search strategies, then synthesizing findings.
|
|
109
|
+
|
|
110
|
+
- Spawn a swarm of researchers across different topics or sources
|
|
111
|
+
- Each agent searches, fetches, reads, and summarizes independently
|
|
112
|
+
- A lead agent collects outputs into a structured report with citations
|
|
113
|
+
- Memory stores findings for future reference across conversations
|
|
114
|
+
- Schedule recurring research runs (daily digest, weekly competitive scan)
|
|
115
|
+
|
|
116
|
+
**Starter kit:** Research Copilot → 1 focused researcher, scale up with subagents.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### OpenClaw Fleet
|
|
121
|
+
|
|
122
|
+
Distribute autonomous agents across multiple machines using OpenClaw gateways — one control plane, many runtimes.
|
|
123
|
+
|
|
124
|
+
- Deploy OpenClaw runtimes on local machines, VPS nodes, or Tailnet peers
|
|
125
|
+
- Each agent targets a different gateway profile (one for code, one for research, one for ops)
|
|
126
|
+
- The operator agent coordinates work across the fleet via delegation and the task board
|
|
127
|
+
- Gateway health, runtime state, and version info visible from the Providers screen
|
|
128
|
+
- Import `SKILL.md` files from any OpenClaw instance into SwarmClaw's skill library
|
|
129
|
+
|
|
130
|
+
**Starter kit:** OpenClaw Fleet → Operator + Remote Builder + Remote Researcher.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### Content Studio
|
|
135
|
+
|
|
136
|
+
A writer/editor pipeline for blogs, docs, newsletters, marketing copy, or social posts.
|
|
137
|
+
|
|
138
|
+
- **Writer** drafts content based on briefs, outlines, and style guides
|
|
139
|
+
- **Editor** tightens structure, fixes tone, and flags missing evidence
|
|
140
|
+
- Schedule daily or weekly content runs with automatic handoff
|
|
141
|
+
- Connect to Slack or Discord to publish directly from the pipeline
|
|
142
|
+
- Image generation agent produces visuals alongside copy
|
|
143
|
+
|
|
144
|
+
**Starter kit:** Content Studio → Writer + Editor pair.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Customer Support Desk
|
|
149
|
+
|
|
150
|
+
Agents answering questions on every platform your users are on, with shared memory and escalation paths.
|
|
151
|
+
|
|
152
|
+
- Bridge a support agent to Discord, Slack, Telegram, WhatsApp, and Teams simultaneously
|
|
153
|
+
- The agent remembers each sender's history, preferences, and open issues
|
|
154
|
+
- Unanswerable questions escalate via `ask_human` or get routed to a specialist agent
|
|
155
|
+
- Schedule a nightly agent to review open threads, follow up on stale conversations, and summarize trends
|
|
156
|
+
- Skills let you codify common support workflows so the agent improves over time
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Crypto Operations
|
|
161
|
+
|
|
162
|
+
Agents with linked wallets for on-chain work — monitoring, trading, signing, and reporting.
|
|
163
|
+
|
|
164
|
+
- Attach Solana or Ethereum wallets to any agent
|
|
165
|
+
- Agents can check balances, simulate transactions, and execute swaps
|
|
166
|
+
- Approval gates require human sign-off before spending above a threshold
|
|
167
|
+
- Schedule periodic balance checks or price-alert sweeps
|
|
168
|
+
- The operator agent coordinates across multiple wallet-holding agents
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Mix and Match
|
|
173
|
+
|
|
174
|
+
These aren't exclusive templates — they're patterns you combine. A virtual company can have a dev team inside it. A personal assistant can spin up a research swarm on demand. An OpenClaw fleet can run your customer support desk.
|
|
175
|
+
|
|
176
|
+
The building blocks are the same: **agents, tools, memory, delegation, schedules, connectors, and skills**. SwarmClaw just gives you the control plane to wire them together.
|
|
177
|
+
|
|
18
178
|
## Release Notes
|
|
19
179
|
|
|
180
|
+
### v1.1.4 Highlights
|
|
181
|
+
|
|
182
|
+
- **Orchestrator agents return as a first-class autonomy mode**: eligible agents can now run scheduled orchestrator wake cycles with their own mission, governance policy, wake interval, cycle cap, Autonomy-desk controls, and setup/editor support.
|
|
183
|
+
- **Runtime durability is much harder to knock over**: the task queue now supports parallel execution with restart-safe swarm state, orphaned running-task recovery, stuck-task idle timeout detection, and provider-health persistence across daemon restarts.
|
|
184
|
+
- **Recovery and safety paths are tighter**: provider errors are classified for smarter failover, unavailable agents defer work instead of burning it, supervisor blocks can create executable notifications, and agent budget limits now gate task execution before work starts.
|
|
185
|
+
- **Temporary session rooms are easier to inspect**: chatrooms now split persistent rooms from temporary session-style rooms so orchestrator or structured-session conversations can stay visible without polluting the normal room list.
|
|
186
|
+
|
|
187
|
+
### v1.1.3 Highlights
|
|
188
|
+
|
|
189
|
+
- **Release integrity repair**: `build:ci` no longer trips over the langgraph checkpoint duplicate-column path, which restores clean build validation for the release line.
|
|
190
|
+
- **Storage writes are safer**: credential and agent saves were tightened to upsert-only behavior and bulk-delete safety guards so tests or scripts cannot accidentally wipe live state.
|
|
191
|
+
- **Plugin-to-extension cleanup finished**: remaining rename residue in scripts and tests was cleaned up so packaging and release tooling stay aligned with the current extensions model.
|
|
192
|
+
|
|
193
|
+
### v1.1.2 Highlights
|
|
194
|
+
|
|
195
|
+
- **Structured Sessions expanded into richer orchestration**: ProtocolRun-based sessions now support dependency-aware step graphs, reusable step outputs, and a broader advanced execution model on the same durable runtime instead of bringing back a separate orchestrator.
|
|
196
|
+
- **Explicit Ollama local/cloud routing**: agents and sessions now persist the user-selected Ollama mode directly, so local Ollama no longer flips to cloud because of model naming or leftover credentials.
|
|
197
|
+
- **Chat and runtime regression hardening**: live-streamed inline media, stale streaming cleanup, exact-output handling, and chat rendering bugs were tightened again, including the recent message-row and avatar rendering regressions.
|
|
198
|
+
- **Nebius and DeepInfra as built-in providers**: both are now first-class providers with setup wizard entries, model discovery, and pre-configured defaults instead of requiring the custom provider workaround.
|
|
199
|
+
- **`stream_options` resilience**: the OpenAI-compatible streaming handler now retries without `stream_options` if a provider rejects it with 400, fixing connectivity for strict endpoints.
|
|
200
|
+
|
|
20
201
|
### v1.1.1 Highlights
|
|
21
202
|
|
|
22
203
|
- **Structured Sessions are now contextual**: start bounded structured runs from direct chats, chatrooms, tasks, missions, or schedules, including a new chatroom `/breakout` command that spins up a focused session from the current room with auto-filled participants and kickoff context.
|
|
@@ -39,9 +220,9 @@ Extension tutorial: https://swarmclaw.ai/docs/extension-tutorial
|
|
|
39
220
|
|
|
40
221
|
## What SwarmClaw Focuses On
|
|
41
222
|
|
|
42
|
-
- **Delegation and background execution**: delegated work, subagents, durable jobs, checkpointing, and background task execution.
|
|
43
|
-
- **Structured Sessions**: temporary bounded runs for one agent or many, launched from context and backed by durable templates, transcripts, outputs, operator controls, and chatroom breakout flows.
|
|
44
|
-
- **Autonomy and memory**: heartbeats, schedules, long-running execution, durable memory, reflection memory, human-context learning, document recall, and project-aware context.
|
|
223
|
+
- **Delegation, orchestrators, and background execution**: delegated work, orchestrator agents, subagents, durable jobs, checkpointing, and background task execution.
|
|
224
|
+
- **Structured Sessions and orchestration**: temporary bounded runs for one agent or many, launched from context and backed by durable templates, branching, loops, parallel joins, transcripts, outputs, operator controls, and chatroom breakout flows.
|
|
225
|
+
- **Autonomy and memory**: heartbeats, orchestrator wake cycles, schedules, long-running execution, durable memory, reflection memory, human-context learning, document recall, and project-aware context.
|
|
45
226
|
- **OpenClaw integration**: named gateway profiles, external runtimes, deploy helpers, config sync, approval handling, and OpenClaw agent file editing.
|
|
46
227
|
- **Runtime skills**: pinned skills, OpenClaw-compatible `SKILL.md` import, on-demand skill execution, and configurable keyword or embedding-based recommendation.
|
|
47
228
|
- **Conversation-to-skill drafts**: draft a reusable skill from a real chat, review it, then approve it into the skill library.
|
|
@@ -120,10 +301,11 @@ Then open `http://localhost:3456`.
|
|
|
120
301
|
|
|
121
302
|
## Core Capabilities
|
|
122
303
|
|
|
123
|
-
- **Providers**: OpenClaw, OpenAI, Anthropic, Ollama, Google, DeepSeek, Groq, Together, Mistral, xAI, Fireworks, plus compatible custom endpoints.
|
|
304
|
+
- **Providers**: OpenClaw, OpenAI, Anthropic, Ollama, Google, DeepSeek, Groq, Together, Mistral, xAI, Fireworks, Nebius, DeepInfra, plus compatible custom endpoints.
|
|
124
305
|
- **Delegation**: built-in delegation to Claude Code, Codex CLI, OpenCode CLI, Gemini CLI, and native SwarmClaw subagents.
|
|
125
306
|
- **Autonomy**: heartbeat loops, schedules, background jobs, task execution, supervisor recovery, mission control, and agent wakeups.
|
|
126
|
-
- **
|
|
307
|
+
- **Orchestration**: durable structured execution with branching, repeat loops, parallel branches, explicit joins, restart-safe run state, and contextual launch from chats, chatrooms, tasks, missions, schedules, and API flows.
|
|
308
|
+
- **Structured Sessions**: reusable bounded runs with templates, facilitators, participants, hidden live rooms, chatroom `/breakout`, durable transcripts, outputs, and operator controls.
|
|
127
309
|
- **Memory**: hybrid recall, graph traversal, journaling, durable documents, project-scoped context, automatic reflection memory, communication preferences, profile and boundary memory, significant events, and open follow-up loops.
|
|
128
310
|
- **Wallets**: balances, transfers, signatures, EVM call/quote/swap flows, and approval-gated execution.
|
|
129
311
|
- **Connectors**: Discord, Slack, Telegram, WhatsApp, Teams, Matrix, OpenClaw, and more.
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import { suspendAgentReferences } from '@/lib/server/agents/agent-cascade'
|
|
|
7
7
|
import { notify } from '@/lib/server/ws-hub'
|
|
8
8
|
import { normalizeAgentSandboxConfig } from '@/lib/agent-sandbox-defaults'
|
|
9
9
|
import { normalizeCapabilitySelection } from '@/lib/capability-selection'
|
|
10
|
+
import { normalizeOrchestratorConfig } from '@/lib/orchestrator-config'
|
|
10
11
|
|
|
11
12
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
13
|
const ops: CollectionOps<any> = { load: () => loadAgents({ includeTrashed: true }), save: saveAgents, topic: 'agents', table: 'agents' }
|
|
@@ -44,9 +45,34 @@ export async function PUT(req: Request, { params }: { params: Promise<{ id: stri
|
|
|
44
45
|
body.apiEndpoint,
|
|
45
46
|
)
|
|
46
47
|
}
|
|
48
|
+
if (body.provider !== undefined && body.provider !== 'ollama' && body.ollamaMode === undefined) {
|
|
49
|
+
agent.ollamaMode = null
|
|
50
|
+
}
|
|
47
51
|
if (body.sandboxConfig !== undefined) {
|
|
48
52
|
agent.sandboxConfig = normalizeAgentSandboxConfig(body.sandboxConfig)
|
|
49
53
|
}
|
|
54
|
+
if (
|
|
55
|
+
body.provider !== undefined
|
|
56
|
+
|| body.orchestratorEnabled !== undefined
|
|
57
|
+
|| body.orchestratorMission !== undefined
|
|
58
|
+
|| body.orchestratorWakeInterval !== undefined
|
|
59
|
+
|| body.orchestratorGovernance !== undefined
|
|
60
|
+
|| body.orchestratorMaxCyclesPerDay !== undefined
|
|
61
|
+
) {
|
|
62
|
+
const orchestratorConfig = normalizeOrchestratorConfig({
|
|
63
|
+
provider: typeof body.provider === 'string' ? body.provider : agent.provider,
|
|
64
|
+
orchestratorEnabled: body.orchestratorEnabled ?? agent.orchestratorEnabled,
|
|
65
|
+
orchestratorMission: body.orchestratorMission ?? agent.orchestratorMission,
|
|
66
|
+
orchestratorWakeInterval: body.orchestratorWakeInterval ?? agent.orchestratorWakeInterval,
|
|
67
|
+
orchestratorGovernance: body.orchestratorGovernance ?? agent.orchestratorGovernance,
|
|
68
|
+
orchestratorMaxCyclesPerDay: body.orchestratorMaxCyclesPerDay ?? agent.orchestratorMaxCyclesPerDay,
|
|
69
|
+
})
|
|
70
|
+
agent.orchestratorEnabled = orchestratorConfig.orchestratorEnabled
|
|
71
|
+
agent.orchestratorMission = orchestratorConfig.orchestratorMission
|
|
72
|
+
agent.orchestratorWakeInterval = orchestratorConfig.orchestratorWakeInterval
|
|
73
|
+
agent.orchestratorGovernance = orchestratorConfig.orchestratorGovernance
|
|
74
|
+
agent.orchestratorMaxCyclesPerDay = orchestratorConfig.orchestratorMaxCyclesPerDay
|
|
75
|
+
}
|
|
50
76
|
if (body.preferredGatewayTags !== undefined) {
|
|
51
77
|
agent.preferredGatewayTags = Array.isArray(body.preferredGatewayTags)
|
|
52
78
|
? body.preferredGatewayTags.filter((tag: unknown): tag is string => typeof tag === 'string' && tag.trim().length > 0)
|
|
@@ -64,6 +90,9 @@ export async function PUT(req: Request, { params }: { params: Promise<{ id: stri
|
|
|
64
90
|
role: target.role,
|
|
65
91
|
provider: (typeof target.provider === 'string' && target.provider.trim() ? target.provider : agent.provider),
|
|
66
92
|
model: typeof target.model === 'string' ? target.model : '',
|
|
93
|
+
ollamaMode: (typeof target.provider === 'string' ? target.provider : agent.provider) === 'ollama'
|
|
94
|
+
? (target.ollamaMode === 'cloud' ? 'cloud' : 'local')
|
|
95
|
+
: null,
|
|
67
96
|
credentialId: target.credentialId ?? null,
|
|
68
97
|
fallbackCredentialIds: Array.isArray(target.fallbackCredentialIds) ? target.fallbackCredentialIds : [],
|
|
69
98
|
apiEndpoint: normalizeProviderEndpoint(
|
|
@@ -7,6 +7,7 @@ import { notify } from '@/lib/server/ws-hub'
|
|
|
7
7
|
import { getAgentSpendWindows } from '@/lib/server/cost'
|
|
8
8
|
import { resolveAgentToolSelection } from '@/lib/agent-default-tools'
|
|
9
9
|
import { normalizeAgentSandboxConfig } from '@/lib/agent-sandbox-defaults'
|
|
10
|
+
import { normalizeOrchestratorConfig } from '@/lib/orchestrator-config'
|
|
10
11
|
import { AgentCreateSchema, formatZodError } from '@/lib/validation/schemas'
|
|
11
12
|
import { z } from 'zod'
|
|
12
13
|
export const dynamic = 'force-dynamic'
|
|
@@ -63,6 +64,14 @@ export async function POST(req: Request) {
|
|
|
63
64
|
return NextResponse.json(formatZodError(parsed.error as z.ZodError), { status: 400 })
|
|
64
65
|
}
|
|
65
66
|
const body = parsed.data
|
|
67
|
+
const orchestratorConfig = normalizeOrchestratorConfig({
|
|
68
|
+
provider: body.provider,
|
|
69
|
+
orchestratorEnabled: body.orchestratorEnabled,
|
|
70
|
+
orchestratorMission: body.orchestratorMission,
|
|
71
|
+
orchestratorWakeInterval: body.orchestratorWakeInterval,
|
|
72
|
+
orchestratorGovernance: body.orchestratorGovernance,
|
|
73
|
+
orchestratorMaxCyclesPerDay: body.orchestratorMaxCyclesPerDay,
|
|
74
|
+
})
|
|
66
75
|
const capabilitySelection = resolveAgentToolSelection({
|
|
67
76
|
hasExplicitTools: Boolean(rawRecord && Object.prototype.hasOwnProperty.call(rawRecord, 'tools')),
|
|
68
77
|
hasExplicitExtensions: Boolean(rawRecord && Object.prototype.hasOwnProperty.call(rawRecord, 'extensions')),
|
|
@@ -79,6 +88,7 @@ export async function POST(req: Request) {
|
|
|
79
88
|
systemPrompt: body.systemPrompt,
|
|
80
89
|
provider: body.provider,
|
|
81
90
|
model: body.model,
|
|
91
|
+
ollamaMode: body.provider === 'ollama' ? (body.ollamaMode || 'local') : null,
|
|
82
92
|
credentialId: body.credentialId,
|
|
83
93
|
fallbackCredentialIds: body.fallbackCredentialIds,
|
|
84
94
|
apiEndpoint: normalizeProviderEndpoint(body.provider, body.apiEndpoint || null),
|
|
@@ -88,6 +98,7 @@ export async function POST(req: Request) {
|
|
|
88
98
|
routingStrategy: body.routingStrategy,
|
|
89
99
|
routingTargets: body.routingTargets?.map((target) => ({
|
|
90
100
|
...target,
|
|
101
|
+
ollamaMode: target.provider === 'ollama' ? (target.ollamaMode || 'local') : null,
|
|
91
102
|
apiEndpoint: normalizeProviderEndpoint(target.provider, target.apiEndpoint || null),
|
|
92
103
|
})),
|
|
93
104
|
delegationEnabled: body.delegationEnabled ?? false,
|
|
@@ -108,6 +119,11 @@ export async function POST(req: Request) {
|
|
|
108
119
|
heartbeatIntervalSec: body.heartbeatIntervalSec,
|
|
109
120
|
heartbeatModel: body.heartbeatModel,
|
|
110
121
|
heartbeatPrompt: body.heartbeatPrompt,
|
|
122
|
+
orchestratorEnabled: orchestratorConfig.orchestratorEnabled,
|
|
123
|
+
orchestratorMission: orchestratorConfig.orchestratorMission,
|
|
124
|
+
orchestratorWakeInterval: orchestratorConfig.orchestratorWakeInterval,
|
|
125
|
+
orchestratorGovernance: orchestratorConfig.orchestratorGovernance,
|
|
126
|
+
orchestratorMaxCyclesPerDay: orchestratorConfig.orchestratorMaxCyclesPerDay,
|
|
111
127
|
elevenLabsVoiceId: body.elevenLabsVoiceId,
|
|
112
128
|
monthlyBudget: body.monthlyBudget ?? null,
|
|
113
129
|
dailyBudget: body.dailyBudget ?? null,
|
|
@@ -25,7 +25,7 @@ function seedAgent(id: string, overrides: Record<string, unknown> = {}) {
|
|
|
25
25
|
fallbackCredentialIds: [],
|
|
26
26
|
apiEndpoint: null,
|
|
27
27
|
gatewayProfileId: null,
|
|
28
|
-
|
|
28
|
+
extensions: ['memory'],
|
|
29
29
|
createdAt: now,
|
|
30
30
|
updatedAt: now,
|
|
31
31
|
...overrides,
|
|
@@ -84,7 +84,7 @@ test('POST /api/agents/[id]/thread reuses an existing thread for a disabled agen
|
|
|
84
84
|
sessionType: 'human',
|
|
85
85
|
agentId: 'agent-thread-disabled-existing',
|
|
86
86
|
parentSessionId: null,
|
|
87
|
-
|
|
87
|
+
extensions: ['memory'],
|
|
88
88
|
tools: ['memory'],
|
|
89
89
|
heartbeatEnabled: false,
|
|
90
90
|
heartbeatIntervalSec: null,
|
|
@@ -104,7 +104,7 @@ test('POST /api/agents/[id]/thread reuses an existing thread for a disabled agen
|
|
|
104
104
|
connectorIdleTimeoutSec: null,
|
|
105
105
|
connectorMaxAgeSec: null,
|
|
106
106
|
mailbox: null,
|
|
107
|
-
connectorContext:
|
|
107
|
+
connectorContext: undefined,
|
|
108
108
|
lastAutoMemoryAt: null,
|
|
109
109
|
lastHeartbeatText: null,
|
|
110
110
|
lastHeartbeatSentAt: null,
|
|
@@ -37,7 +37,7 @@ export async function POST(req: Request) {
|
|
|
37
37
|
reason: typeof body.reason === 'string' ? body.reason : null,
|
|
38
38
|
engagedBy: typeof body.engagedBy === 'string' ? body.engagedBy : 'user',
|
|
39
39
|
})
|
|
40
|
-
stopDaemon({ source: `api/autonomy/estop:${level}` })
|
|
40
|
+
await stopDaemon({ source: `api/autonomy/estop:${level}` })
|
|
41
41
|
const cancelled = level === 'all'
|
|
42
42
|
? cancelAllRuns('Cancelled because all estop is engaged.')
|
|
43
43
|
: { cancelledQueued: 0, abortedRunning: 0 }
|
|
@@ -35,7 +35,7 @@ test('chatroom route prevents duplicate chained replies when an already-queued a
|
|
|
35
35
|
name: 'Alpha',
|
|
36
36
|
provider: 'chatroom-provider',
|
|
37
37
|
model: 'room-model',
|
|
38
|
-
|
|
38
|
+
extensions: [],
|
|
39
39
|
createdAt: now,
|
|
40
40
|
updatedAt: now,
|
|
41
41
|
},
|
|
@@ -44,7 +44,7 @@ test('chatroom route prevents duplicate chained replies when an already-queued a
|
|
|
44
44
|
name: 'Beta',
|
|
45
45
|
provider: 'chatroom-provider',
|
|
46
46
|
model: 'room-model',
|
|
47
|
-
|
|
47
|
+
extensions: [],
|
|
48
48
|
createdAt: now,
|
|
49
49
|
updatedAt: now,
|
|
50
50
|
},
|
|
@@ -183,7 +183,7 @@ test('chatroom route forwards tool activity and records one reply per participat
|
|
|
183
183
|
name: 'Alpha',
|
|
184
184
|
provider: 'chatroom-tool-provider',
|
|
185
185
|
model: 'room-tool-model',
|
|
186
|
-
|
|
186
|
+
extensions: ['shell'],
|
|
187
187
|
createdAt: now,
|
|
188
188
|
updatedAt: now,
|
|
189
189
|
},
|
|
@@ -192,7 +192,7 @@ test('chatroom route forwards tool activity and records one reply per participat
|
|
|
192
192
|
name: 'Beta',
|
|
193
193
|
provider: 'chatroom-tool-provider',
|
|
194
194
|
model: 'room-tool-model',
|
|
195
|
-
|
|
195
|
+
extensions: ['shell'],
|
|
196
196
|
createdAt: now,
|
|
197
197
|
updatedAt: now,
|
|
198
198
|
},
|
|
@@ -256,7 +256,7 @@ test('chatroom route forwards tool activity and records one reply per participat
|
|
|
256
256
|
return { fullText: reply, finalResponse: reply }
|
|
257
257
|
}
|
|
258
258
|
if (agentId === 'beta') {
|
|
259
|
-
const reply = 'Beta reviewed the
|
|
259
|
+
const reply = 'Beta reviewed the extension path and agrees with Alpha.'
|
|
260
260
|
opts.write('data: ' + JSON.stringify({ t: 'r', text: reply }) + '\\n')
|
|
261
261
|
return { fullText: reply, finalResponse: reply }
|
|
262
262
|
}
|
|
@@ -268,7 +268,7 @@ test('chatroom route forwards tool activity and records one reply per participat
|
|
|
268
268
|
new Request('http://local/api/chatrooms/room_1/chat', {
|
|
269
269
|
method: 'POST',
|
|
270
270
|
headers: { 'content-type': 'application/json' },
|
|
271
|
-
body: JSON.stringify({ senderId: 'user', text: 'Please inspect the workspace and
|
|
271
|
+
body: JSON.stringify({ senderId: 'user', text: 'Please inspect the workspace and extension path.' }),
|
|
272
272
|
}),
|
|
273
273
|
{ params: Promise.resolve({ id: 'room_1' }) },
|
|
274
274
|
)
|
|
@@ -48,7 +48,7 @@ test('chat route keeps long-lived user runs alive after stream disconnect and re
|
|
|
48
48
|
name: 'Workbench Agent',
|
|
49
49
|
provider: 'workbench-provider',
|
|
50
50
|
model: 'wb-model',
|
|
51
|
-
|
|
51
|
+
extensions: [],
|
|
52
52
|
createdAt: now,
|
|
53
53
|
updatedAt: now,
|
|
54
54
|
},
|
|
@@ -67,7 +67,7 @@ test('chat route keeps long-lived user runs alive after stream disconnect and re
|
|
|
67
67
|
lastActiveAt: now,
|
|
68
68
|
sessionType: 'human',
|
|
69
69
|
agentId: 'agent_1',
|
|
70
|
-
|
|
70
|
+
extensions: [],
|
|
71
71
|
},
|
|
72
72
|
})
|
|
73
73
|
|
|
@@ -159,7 +159,7 @@ test('chat route heartbeat runs stay internal and do not persist terminal ack te
|
|
|
159
159
|
name: 'Heartbeat Agent',
|
|
160
160
|
provider: 'heartbeat-provider',
|
|
161
161
|
model: 'hb-model',
|
|
162
|
-
|
|
162
|
+
extensions: [],
|
|
163
163
|
heartbeatEnabled: true,
|
|
164
164
|
createdAt: now,
|
|
165
165
|
updatedAt: now,
|
|
@@ -180,7 +180,7 @@ test('chat route heartbeat runs stay internal and do not persist terminal ack te
|
|
|
180
180
|
sessionType: 'human',
|
|
181
181
|
agentId: 'agent_1',
|
|
182
182
|
heartbeatEnabled: true,
|
|
183
|
-
|
|
183
|
+
extensions: [],
|
|
184
184
|
},
|
|
185
185
|
})
|
|
186
186
|
|
|
@@ -279,7 +279,7 @@ test('chat route queues a second user message behind the first run and completes
|
|
|
279
279
|
name: 'Queue Agent',
|
|
280
280
|
provider: 'queue-provider',
|
|
281
281
|
model: 'queue-model',
|
|
282
|
-
|
|
282
|
+
extensions: [],
|
|
283
283
|
createdAt: now,
|
|
284
284
|
updatedAt: now,
|
|
285
285
|
},
|
|
@@ -298,7 +298,7 @@ test('chat route queues a second user message behind the first run and completes
|
|
|
298
298
|
lastActiveAt: now,
|
|
299
299
|
sessionType: 'human',
|
|
300
300
|
agentId: 'agent_1',
|
|
301
|
-
|
|
301
|
+
extensions: [],
|
|
302
302
|
},
|
|
303
303
|
})
|
|
304
304
|
|
|
@@ -356,7 +356,7 @@ test('chat route queues a second user message behind the first run and completes
|
|
|
356
356
|
assistantReplies,
|
|
357
357
|
runStatuses: runs.listRuns({ sessionId: 'sess_1' }).map((entry) => entry.status),
|
|
358
358
|
}))
|
|
359
|
-
`, { prefix: 'swarmclaw-chat-route-
|
|
359
|
+
`, { prefix: 'swarmclaw-chat-route-extensions-' })
|
|
360
360
|
|
|
361
361
|
assert.match(output.firstRunMeta, /"position":0/)
|
|
362
362
|
assert.match(output.secondRunMeta, /"position":1/)
|
|
@@ -367,7 +367,7 @@ test('chat route queues a second user message behind the first run and completes
|
|
|
367
367
|
assert.deepEqual(output.runStatuses, ['completed', 'completed'])
|
|
368
368
|
})
|
|
369
369
|
|
|
370
|
-
test('chat route forwards
|
|
370
|
+
test('chat route forwards extension-path tool activity when an extension-enabled run uses streamAgentChat', () => {
|
|
371
371
|
const output = runWithTempDataDir<{
|
|
372
372
|
toolCalls: string[]
|
|
373
373
|
toolResults: string[]
|
|
@@ -382,10 +382,10 @@ test('chat route forwards plugin-path tool activity when a plugin-enabled run us
|
|
|
382
382
|
const route = routeMod.default || routeMod
|
|
383
383
|
const stream = streamMod.default || streamMod
|
|
384
384
|
|
|
385
|
-
providers.PROVIDERS['
|
|
386
|
-
id: '
|
|
387
|
-
name: '
|
|
388
|
-
models: ['
|
|
385
|
+
providers.PROVIDERS['extension-provider'] = {
|
|
386
|
+
id: 'extension-provider',
|
|
387
|
+
name: 'Extension Provider',
|
|
388
|
+
models: ['extension-model'],
|
|
389
389
|
requiresApiKey: false,
|
|
390
390
|
requiresEndpoint: false,
|
|
391
391
|
handler: { streamChat: async () => '' },
|
|
@@ -395,10 +395,10 @@ test('chat route forwards plugin-path tool activity when a plugin-enabled run us
|
|
|
395
395
|
storage.saveAgents({
|
|
396
396
|
agent_1: {
|
|
397
397
|
id: 'agent_1',
|
|
398
|
-
name: '
|
|
399
|
-
provider: '
|
|
400
|
-
model: '
|
|
401
|
-
|
|
398
|
+
name: 'Extension Agent',
|
|
399
|
+
provider: 'extension-provider',
|
|
400
|
+
model: 'extension-model',
|
|
401
|
+
extensions: ['web'],
|
|
402
402
|
createdAt: now,
|
|
403
403
|
updatedAt: now,
|
|
404
404
|
},
|
|
@@ -406,18 +406,18 @@ test('chat route forwards plugin-path tool activity when a plugin-enabled run us
|
|
|
406
406
|
storage.saveSessions({
|
|
407
407
|
sess_1: {
|
|
408
408
|
id: 'sess_1',
|
|
409
|
-
name: '
|
|
409
|
+
name: 'Extension Session',
|
|
410
410
|
cwd: process.env.WORKSPACE_DIR,
|
|
411
411
|
user: 'workbench',
|
|
412
|
-
provider: '
|
|
413
|
-
model: '
|
|
412
|
+
provider: 'extension-provider',
|
|
413
|
+
model: 'extension-model',
|
|
414
414
|
claudeSessionId: null,
|
|
415
415
|
messages: [],
|
|
416
416
|
createdAt: now,
|
|
417
417
|
lastActiveAt: now,
|
|
418
418
|
sessionType: 'human',
|
|
419
419
|
agentId: 'agent_1',
|
|
420
|
-
|
|
420
|
+
extensions: ['web'],
|
|
421
421
|
},
|
|
422
422
|
})
|
|
423
423
|
|
|
@@ -460,7 +460,7 @@ test('chat route forwards plugin-path tool activity when a plugin-enabled run us
|
|
|
460
460
|
toolOutput: 'Fetched queue health summary',
|
|
461
461
|
toolCallId: 'tool-1',
|
|
462
462
|
}) + '\\n')
|
|
463
|
-
const reply = 'Queue looks healthy and no
|
|
463
|
+
const reply = 'Queue looks healthy and no extension errors were observed.'
|
|
464
464
|
opts.write('data: ' + JSON.stringify({ t: 'r', text: reply }) + '\\n')
|
|
465
465
|
return { fullText: reply, finalResponse: reply }
|
|
466
466
|
})
|
|
@@ -488,9 +488,9 @@ test('chat route forwards plugin-path tool activity when a plugin-enabled run us
|
|
|
488
488
|
} finally {
|
|
489
489
|
stream.setStreamAgentChatForTest(null)
|
|
490
490
|
}
|
|
491
|
-
`, { prefix: 'swarmclaw-chat-route-
|
|
491
|
+
`, { prefix: 'swarmclaw-chat-route-extension-events-' })
|
|
492
492
|
|
|
493
493
|
assert.deepEqual(output.toolCalls, ['web'])
|
|
494
494
|
assert.deepEqual(output.toolResults, ['Fetched queue health summary'])
|
|
495
|
-
assert.deepEqual(output.assistantReplies, ['Queue looks healthy and no
|
|
495
|
+
assert.deepEqual(output.assistantReplies, ['Queue looks healthy and no extension errors were observed.'])
|
|
496
496
|
})
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import {
|
|
2
|
+
import { loadStoredItem, upsertStoredItem } from '@/lib/server/storage'
|
|
3
3
|
import { notFound } from '@/lib/server/collection-helpers'
|
|
4
|
-
import { getSessionRunState } from '@/lib/server/runtime/session-run-manager'
|
|
5
4
|
import { materializeStreamingAssistantArtifacts } from '@/lib/chat/chat-streaming-state'
|
|
6
5
|
import { appendSessionNote } from '@/lib/server/session-note'
|
|
7
6
|
import type { Message, Session } from '@/types'
|
|
@@ -12,9 +11,9 @@ export async function GET(req: Request, { params }: { params: Promise<{ id: stri
|
|
|
12
11
|
if (!session) return notFound()
|
|
13
12
|
session.messages = Array.isArray(session.messages) ? session.messages : []
|
|
14
13
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
if (!
|
|
14
|
+
const sessionClaimsActive = session.active === true
|
|
15
|
+
|| (typeof session.currentRunId === 'string' && session.currentRunId.trim().length > 0)
|
|
16
|
+
if (!sessionClaimsActive && materializeStreamingAssistantArtifacts(session.messages)) {
|
|
18
17
|
upsertStoredItem('sessions', id, session)
|
|
19
18
|
}
|
|
20
19
|
|
|
@@ -64,6 +64,11 @@ export async function PUT(req: Request, { params }: { params: Promise<{ id: stri
|
|
|
64
64
|
else if (agentIdUpdateProvided && linkedRoute?.model) session.model = linkedRoute.model
|
|
65
65
|
else if (agentIdUpdateProvided && linkedAgent?.model !== undefined) session.model = linkedAgent.model
|
|
66
66
|
|
|
67
|
+
if (updates.ollamaMode !== undefined) session.ollamaMode = updates.ollamaMode
|
|
68
|
+
else if (updates.provider !== undefined && updates.provider !== 'ollama') session.ollamaMode = null
|
|
69
|
+
else if (agentIdUpdateProvided && linkedRoute) session.ollamaMode = linkedRoute.ollamaMode ?? null
|
|
70
|
+
else if (agentIdUpdateProvided && linkedAgent) session.ollamaMode = linkedAgent.ollamaMode ?? null
|
|
71
|
+
|
|
67
72
|
if (updates.credentialId !== undefined) session.credentialId = updates.credentialId
|
|
68
73
|
else if (agentIdUpdateProvided && linkedRoute) session.credentialId = linkedRoute.credentialId ?? null
|
|
69
74
|
else if (agentIdUpdateProvided && linkedAgent) session.credentialId = linkedAgent.credentialId ?? null
|